Awk / и т.д .: Извлечь совпадения из файла - PullRequest
0 голосов
/ 12 июня 2009

У меня есть HTML-файл, и я хотел бы извлечь текст между тегами <li> и </li>. Есть, конечно, миллион способов сделать это, но я подумал, что было бы полезно получить больше привычки делать это с помощью простых команд оболочки:

awk '/<li[^>]+><a[^>]+>([^>]+)<\/a>/m' cities.html

Проблема в том, что это печатает все , тогда как я просто хочу напечатать соответствие в скобках - ([^>]+) - либо awk не поддерживает это, либо я некомпетентен. Последнее кажется более вероятным. Если вы хотите применить предоставленное регулярное выражение к файлу и извлечь только указанные совпадения, как бы вы это сделали? Я уже знаю полдюжины других способов, но мне не хочется позволять awk выиграть в этом раунде;)

Редактировать: данные плохо структурированы, поэтому использование позиционных совпадений ($1, $2, etc.) не допускается.

Ответы [ 5 ]

2 голосов
/ 12 июня 2009

Если вы хотите сделать это в общем случае, когда ваши теги списка могут содержать любую допустимую разметку HTML, тогда awk - неправильный инструмент. Подходящим инструментом для работы будет HTML-парсер, которому можно доверять, чтобы исправить все мелкие детали парсинга HTML, включая варианты HTML и искаженный HTML.

Если вы делаете это для особого случая, когда вы можете управлять форматированием HTML, тогда вы можете заставить awk работать на вас. Например, предположим, что вы можете гарантировать, что каждый элемент списка никогда не занимает более одной строки, всегда оканчивается на </li> в одной строке, никогда не содержит никакой разметки (например, список, содержащий список), тогда вы можете использовать awk для этого, но вам нужно написать целую awk программу, которая сначала находит строки, содержащие элементы списка, а затем использует другие команды awk, чтобы найти только интересующую вас подстроку.

Но в целом, awk не подходит для этой работы.

1 голос
/ 13 июля 2010
gawk -F'<li>' -v RS='</li>' 'RT{print $NF}' file

Работал для меня очень хорошо.

0 голосов
/ 12 июня 2009

По вашему сценарию, если вы можете получить то, что вы хотите (это означает, что тег <li> и <a> находятся в одной строке.);

$ cat test.html | awk 'sub(/<li[^>]*><a[^>]*>/,"")&&sub(/<\/a>.*/,"")'

или

$ cat test.html | gawk '/<li[^>]*><a[^>]*>(.*?)<\/a>.*/&&$0=gensub(/<li[^>]*><a[^>]*>(.*?)<\/a>.*/,"\\1", 1)'

Первый - для каждого awk, второй - для gnu awk.

0 голосов
/ 12 июня 2009

Не знаю awk, а как насчет Perl?

tr -d '\012' the.html | perl \
-e '$text = <>;' -e 'while ( length( $text) > 0)' \
-e '{ $text =~ /<li>(.*?)<\/li>(.*)/; $target = $1; $text = $2; print "$target\n" }'

1) удалить переводы строк из файла, передать через perl

2) инициализируйте переменную полным текстом, начните цикл, пока текст не исчезнет

3) выполнить «не жадное» сопоставление для материала, ограниченного тегами list-item, сохранить и распечатать цель, настроить для следующего прохода

Имеет смысл? (предупреждение, сам не пробовал этот код, скоро нужно домой ...)

P.S. - "perl -n" - это режим Awk (nawk?). Perl в значительной степени является надмножеством Awk, поэтому я никогда не удосужился выучить Awk.

0 голосов
/ 12 июня 2009

Я вижу несколько проблем:

  • У шаблона есть завершающий символ 'm', который важен для многострочных совпадений в Perl, но Awk не использует Perl-совместимые регулярные выражения. (По крайней мере, стандартный (не GNU) awk этого не делает.)
  • Игнорируя это, шаблон, похоже, ищет «элемент начального списка», за которым следует привязка «<a>» к «</a>», а не элемент конечного списка.
  • Вы ищете все, что не является '>' как тело якоря; это не является автоматически неправильным, но может быть более обычным искать что-то, что не является «<», или что-либо, что не является ни тем, ни другим.
  • Awk не выполняет многострочный поиск.
  • В Awk '$1' обозначает первое поле, где поля разделены символами-разделителями полей, по умолчанию это пробел.
  • В классическом nawk (как задокументировано в 'sed & awk' книжном сборнике 1991 года) нет механизма вытягивания подполей из спичек и т. Д.

Не ясно, что Awk - правильный инструмент для этой работы. Действительно, не совсем ясно, что регулярные выражения являются подходящим инструментом для этой работы.

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