2012-03-15 2 views
3

У меня есть HTML-страница со следующим содержанием:Как остановить алчность, используя Grep из Баша

[...] 
<tr><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.zip">play-1.0.2.zip</a></td></tr> 
[...] 

И я хотел бы, чтобы извлечь только

play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 

, чтобы затем найти самую последнюю версию (в этом случае было бы play-1.0.2.1.zip)

Так что я попытался с

cat tmp.html | grep "<a href=\".*\"" 

<a href="play-1.0.1.zip">play-1.0.1.zip</a></td><td class="m" 
<a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td><td class="m" 
<a href="play-1.0.2.zip">play-1.0.2.zip</a></td><td class="m" 

Так что я попытался с ленивым:

cat tmp.html | grep "<a href=\".*?\"" 

и отрицая котировки

cat tmp.html | grep "<a href=\"[^\"]*?\"" 

оба они не возвращаются ничего

мне нужно получить только совпадающую часть (а не href), а затем найти последние, но я stu ск с этой проблемой жадностью ...

-

спасибо за ответы на все вопросы, все они были очень полезны, это трудно решить, какой из них правильный, в конце концов, я решил его с :

grep -v '.*-RC.*' index.html | grep -oP 'play-1.*?.zip' | sort -Vru | head -1 
+1

Grep -E " strkol

+1

Нет необходимости использовать 'cat tmp.html' с grep, потому что grep может обрабатывать файлы самостоятельно. Вы должны использовать 'grep -E pattern tmp.html'. – piotrekkr

ответ

6

В отличие от других ответов, это может быть сделано исключительно с Grep.

Ваш выход немного отличается от вашего ввода - появляются дополнительные элементы. Для целей этого ответа я собираюсь использовать этот файл:

<tr><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.zip">play-1.0.2.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 

Здесь нужно сделать несколько вещей. Во-первых, вам нужно установить правильные grep-переключатели. Вам нужно:

  • -o для вывода только совпадающую часть каждой строки
  • -P использовать Perl совместимый механизм регулярных выражений

Теперь вы можете использовать?Модификатор для предотвращения жадных соответствий:

grep -o -P '<a href=".*?"' test.html 

<a href="play-1.0.1.zip" 
<a href="play-1.0.1.zip" 
<a href="play-1.0.2.1.zip" 
<a href="play-1.0.1.zip" 
<a href="play-1.0.2.zip" 
<a href="play-1.0.1.zip" 

Это не совсем верно, так что мы будем якорем регулярного выражения в первый матч линии:

grep -o -P '^<tr><td class="n"><a href=".*?"' test.html 

<tr><td class="n"><a href="play-1.0.1.zip" 
<tr><td class="n"><a href="play-1.0.2.1.zip" 
<tr><td class="n"><a href="play-1.0.2.zip" 

Это правильные данные, но слишком много хлама , Нам нужно использовать утверждения с нулевой шириной (часть синтаксиса PCRE). По существу биты регулярного выражения, которые не учитываются для сопоставленного шаблона.

grep -o -P '(?<=^<tr><td class="n"><a href=").*?(?=")' test.html 

play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 

Теперь вы можете делать все, что нужно для сортировки списка. Более подробную информацию о нулевой ширины утверждений можно найти здесь: http://www.regular-expressions.info/lookaround.html

+0

+1 хороший ответ, чтобы показать, как вы перебираете регулярное выражение. –

2

попробовать с -E переключателем:

[email protected]:~$ echo '<a href="play-1.0.1.zip">play-1.0.1.zip</a></td>' | grep -E '<a href=".*?"' 
<a href="play-1.0.1.zip">play-1.0.1.zip</a></td> 
+1

Это работает, потому что grep по умолчанию использует основной механизм регулярных выражений. Переключатели '-E',' -F' и '-P' меняют используемый двигатель. Дополнительную информацию см. На странице руководства. –

1

grep не кажется, что правильный инструмент для этого, так как вы хотите, чтобы извлечь submatch.

Вот Perl один вкладыш, который будет делать это, хотя:

$ perl -ne 'while(/<a href="([^"]+)"/g){print $1, "\n";}' input 
play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 
3
$ grep 'href=' tmp.html | sed 's/.*href="\(.*\)".*/\1/' 
play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 
+0

Хорошо, наконец, решение 'sed':) ...Ну, похоже, это не работает, если файл содержит другие строки, так что это можно сделать после 'grep'? –

+0

да, правильно, исправлено, все еще самое короткое решение :-) – strkol

5

С GNU инструментов, вы можете сделать

grep -oP '(?<=<td class="n"><a href=")[^"]+' | sort -Vr | head -1 
0

Awk является отличным инструментом, если вы знаете, число полей:

awk -F\" '$4 ~ /play.*zip/{ print $4 }' 

Или это своего рода грязный путь; поиск всех почтовых файлов:

cat file | tr '"' '\n' | grep -e '.zip$' | sort -u 

Это позволит получить все почтовые файлы для вас. Утилита tr слишком много используется, она просто заменяет символ, в этом случае заменяя каждую двойную кавычку новой строкой, красиво получая цитированные данные на своей собственной линии, где вы можете ее grep. Сорт -u позволяет избежать дублирования.

0

Perl-путь:

cat thefile | perl -anF'"' -e 'print $F[3],"\n";($v)=$F[3]=~/(\d.*\d)/;$m=$v if$v gt $m;}{print "max=$m\n";' 

выход:

play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 
max=1.0.2.1 
1

Используя ответ предоставленный Крейг Эндрюс с добавлением поддержки OSX.

grep -o -P '(?<=^<tr><td class="n"><a href=").*?(?=")' /test.html | sort -n -r -k1.10,12 

Результат:

play-1.0.2.1.zip 
play-1.0.2.zip 
play-1.0.1.zip 
+0

Точно так же, как добавленная помощь для тех пользователей только xs x. sort -V по умолчанию недоступен в OSX. Это также должно работать на других машинах на базе UNIX. – E1Suave

3

Не видел вырезать (и мне нравится его скорость краткость &) так:

покрой -d \»-f4 TMP. html | sort -Vu | tail -1

мощность:

play-1.0.2.1.zip

Смежные вопросы