Пример совместной работы команд wget egrep sed


В статье Команда wget - пример использования был показан простенький пример использования команды wget в цикле while для закачки нескольких файлов. В комментариях к этой статье посетитель Иван спрашивал как можно с помощью wget выкачать фотографии с сайта http://photo.rdx.cz/index.php?show=album&aid=412 и через некоторое время сам же написал ответ. Вот эта команда:

1
2
3
4
5
6
wget -qO- 'http://photo.rdx.cz/index.php?show=album&aid=412' |
egrep -o 'index.php\?show=photo&pid=[0-9]+&aid=412' |
sed 's/.*pid=\([0-9]*\).*/\1/' |
while read num; do wget -P photo.rdx http://photo.rdx.cz/"$(wget -qO-
"http://photo.rdx.cz/index.php?show=photo&pid=$num&aid=412″ |
egrep -o '"showphoto/.+jpg"' | sed 's/"//g')"; done

Не все в этой конструкции для меня в ней было понятно, поэтому решил когда будет время разобрать ее. Время нашлось (пришлось немного погуглить и даже на форум http://www.cyberforum.ru/freebsd/ один раз занесло) и ниже идет пояснение как работает эта составная команда. Пример разбирался в Ubuntu 10.04. Если где ошибся - поправляйте. Итак, начну по частям.

1
wget -qO- 'http://photo.rdx.cz/index.php?show=album&aid=412'

Ключ -q - отключает вывод служебной информации wget. То есть чтобы не выводился текст примерно следующего содержания:

1
2
3
4
5
--2011-06-16 15:33:03--  http://photo.rdx.cz/index.php?show=album&aid=412
Преобразование адреса photo.rdx.cz... 92.240.234.198
Устанавливается соединение с photo.rdx.cz|92.240.234.198|:80... соединились.
Запрос HTTP послан, ожидание ответа... 200 OK
Длина: нет информации [text/html]

С ключом q эта информация выводится не будет.

Опция O - позволяет записать результат команды wget в файл, а если вместо имени файла подставить знак “минус” (O-), то вывод будет направлен в stdout и по умолчанию отобразится на экране. То есть в данном случае, страница http://photo.rdx.cz/index.php?show=album&aid=412 не будет сохранена на диске, а будет выведена (содержимое страницы) в stdout на экран.

Далее идет команда

1
egrep -o 'index.php\?show=photo&pid=[0-9]+&aid=412'

Команда egrep (аналог команды grep -E) позволяет фильтровать входящий поток. В данном случае с использованием расширенных регулярных выражений. Если посмотреть содержимое страницы http://photo.rdx.cz/index.php?show=album&aid=412, то там мы видим ссылки на фотографии которые имеют вид:

1
2
3
<a href=index.php?show=photo&pid=12127&aid=412>
<a href=index.php?show=photo&pid=12145&aid=412>
<a href=index.php?show=photo&pid=12147&aid=412>

То есть ссылки однотипны и меняется только число. Описать данную строку нужно заменив число на выражение [0-9]+. Знак “плюс” означает, что предыдущее выражение встречается один или более раза. То есть, чтобы не писать конструкцию вида [0-9][0-9][0-9][0-9][0-9], более лаконично можно записать как [0-9]+.

Команда

1
2
wget -qO- 'http://photo.rdx.cz/index.php?show=album&aid=412' |
egrep -o 'index.php\?show=photo&pid=[0-9]+&aid=412'

выведет на экран все ссылки на фотографии:

1
2
3
4
5
index.php?show=photo&pid=12075&aid=412
index.php?show=photo&pid=12076&aid=412
..................
index.php?show=photo&pid=12148&aid=412
index.php?show=photo&pid=12149&aid=412

Теперь зная все ссылки на фотографии нужно перейти по каждой из них, чтобы узнать реальный адрес файла jpg. Если перейти по ссылке http://photo.rdx.cz/index.php?show=photo&pid=12075&aid=412 и посмотреть ее исходный код (команда ctrl+U) в браузере, то увидим такую строку

1
<img src="showphoto/816p12075.jpg" ......>

Эта ссылка с добавлением имени сайта (получается вот так - http://photo.rdx.cz/showphoto/816p12075.jpg) и есть прямая ссылка на фотографию которую нам нужно получить и передать еще одной команде wget для закачки. Продолжаем.

Сначала извлечем из полученных строк числа. Для этого используем команду sed:

1
sed 's/.*pid=\([0-9]*\).*/\1/'

sed - это мощная утилита которая позволяет обрабатывать построчно текстовую информацию. В данном случае имеет место один из самых распространенных вариантов использования sed: sed s/regexp/replacement/. При такой записи, sed будет искать строки которые содержат regexp и заменять их на выражение replacement.

В данном примере, в качестве regexp будет, выражение .*pid=\([0-9]*\).*. В этом выражении используется конструкция \([0-9]*\). \(…\) - это служебное выражение, которое используется для того, чтобы выделить часть regexp. В качестве replacement можно использовать выражение вида \n, где n - это число от 1 до 9, которое обозначает порядковый номер конструкции \(…\). В нашем выражении она одна, поэтому в качестве replacemen записано \1. Таким образом получается, что все строки которые соответствуют выражению .*pid=\([0-9]*\).* (а ему соответствуют все строки) будут заменены на выражение [0-9]*, а это и есть искомое число. Выполнив команду:

1
2
3
wget -qO- 'http://photo.rdx.cz/index.php?show=album&aid=412' |
egrep -o 'index.php\?show=photo&pid=[0-9]+&aid=412' |
sed 's/.*pid=\([0-9]*\).*/\1/'

получаем на выходе искомые числа.

Теперь рассмотрим следующую конструкцию

1
2
"$(wget -qO- "http://photo.rdx.cz/index.php?show=photo&pid=$num&aid=412" |
egrep -o '"showphoto/.+jpg"' | sed 's/"//g')"

Она по сути аналогична той которую мы рассматривали в самом начале. Та же связка wget, egrep, sed. $num - будет возвращать числа которые мы выбрали с помощью первой конструкции wget, egrep, sed. Откуда взялось $num чуть позже.

egrep -o ‘”showphoto/.+jpg”‘ - ищет строку вида “showphoto/81p12077.jpg”, а sed ’s/”//g’ - убирает в данной строке все двойные кавычки. В результате получается строка вида showphoto/81p12077.jpg, которая возвращается благодаря конструкции “$()”.

Теперь смотрим последний фрагмент:

1
while read num; do wget -P photo.rdx http://photo.rdx.cz/"$()"; done

Данная конструкция (while read num) будет принимать строки, которые были определены первой связкой wget, egrep, sed и обрабатывать их в цикле. То есть команда read (это встроенная команда bash) будет принимать строку (присваивать ее значение переменной num) и затем будет выполнена команда wget -P photo.rdx http://photo.rdx.cz/”$()”, которая скопирует фотографию в каталог photo.rdx. Так как команда read находится в цикле (while), то будет получена следующая строка и т.д.

Не знаю удалось ли мне доступно расшифровать для вас весь этот блок, но я старался :)
Кстати, участок egrep -o ‘”showphoto/.+jpg”‘ | sed ’s/”//g’ именно в данном конкретном примере можно немного сократить заменив его на egrep -o ’showphoto/.+[0-9].jpg’ убрав при этом команду sed.

Статьи и новости схожей тематики:

Один комментарий

  1. Дроид:

    ‘/home/ddd/Рабочий стол/jpg/jpg.sh’
    /home/ddd/Рабочий стол/jpg/jpg.sh: line 7: unexpected EOF while looking for matching `”
    /home/ddd/Рабочий стол/jpg/jpg.sh: line 8: ошибка синтаксиса: неожиданный конец файла
    Записал в файл запустил - вот такой результат

    Ответить

Оставьте свой отзыв