Пример совместной работы команд 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.
Дроид:
‘/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: ошибка синтаксиса: неожиданный конец файла
Записал в файл запустил - вот такой результат
Ответить
1 августа 2012, 6:43