Как остановить жадность, используя grep из bash - PullRequest
3 голосов
/ 15 марта 2012

У меня есть HTML-страница со следующим содержанием:

[...]
<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), а затем найти последнюю версию, но я застрял с этой проблемой жадности ...

-

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

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

Ответы [ 9 ]

6 голосов
/ 15 марта 2012

В отличие от других ответов, это можно сделать полностью с помощью 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

5 голосов
/ 15 марта 2012

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

grep -oP '(?<=<td class="n"><a href=")[^"]+' | sort -Vr | head -1
3 голосов
/ 27 ноября 2012

Не видел среза (и мне нравится его краткость и скорость), поэтому:

cut -d \ "-f4 tmp.html | sort -Vu | tail -1

выход:

play-1.0.2.1.zip

3 голосов
/ 15 марта 2012
$ grep 'href=' tmp.html | sed 's/.*href="\(.*\)".*/\1/'
play-1.0.1.zip
play-1.0.2.1.zip
play-1.0.2.zip
2 голосов
/ 15 марта 2012

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

piotrekkr@piotrekkr-desktop:~$ 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 голос
/ 10 апреля 2012

Используя ответ, предоставленный Крейг Эндрюс с добавлением поддержки 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
1 голос
/ 15 марта 2012

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

Вот 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
0 голосов
/ 15 марта 2012

Способ 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
0 голосов
/ 15 марта 2012

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...