Как использовать sed-awk-gawk для отображения подходящей строки - PullRequest
0 голосов
/ 24 февраля 2011

У меня есть файл с именем 'res', который состоит из 29374 символов данных http в одну строку. Внутри него есть несколько http-ссылок, но я хочу отображать только те, которые заканчиваются на '/ idNNNNNNNNN', где N - это цифра. На самом деле меня интересует только строка «idNNNNNNNNN». Я пробовал с:

cat res | sed -n '0,/.*\(id[0-9]*\).*/s//\1/p'

но я получаю весь файл. Вы знаете, как это сделать?

Ответы [ 4 ]

2 голосов
/ 24 февраля 2011
perl -n -E 'say $1 while m!/id(\d{9})!g' input-file

должно работать. Это предполагает ровно 9 цифр; это {9} в приведенном выше. Вы можете выбрать 8 или 9 ({8,9}), 8 или более ({8,}), до 9 ({0,9}) и т. Д.

Пример этой работы:

$ echo -n 'junk jumk http://foo/id231313 junk lalala http://bar/id23123 asda' | perl -n -E 'say $1 while m!id(\d{0,9})!g'
231313
23123

Конечно, это вариант с 0 по 9.

Если вы застряли с perl до 5.10, используйте -e вместо -E и print "$1\n" вместо say $1.

Как это работает

Первый - это два аргумента командной строки для Perl. -n говорит Perl читать строку из стандартного ввода или файлов, заданных в командной строке, построчно, устанавливая $_ для каждой строки. $_ является целью Perl по умолчанию для многих вещей, включая совпадения с регулярными выражениями. -E просто сообщает Perl, что следующим аргументом является однострочный Perl, использующий новые возможности языка (по сравнению с -e, который не использует расширения 5.10).

Итак, глядя на одну строку: say означает распечатать какое-то значение, за которым следует новая строка. $1 - первый захват регулярного выражения (захват производится в круглых скобках в регулярных выражениях). while - это циклическая конструкция, с которой вы, вероятно, знакомы. m является оператором совпадения, ! после него является разделителем регулярного выражения (обычно вы видите / здесь, но поскольку шаблон содержит /, проще использовать что-то другое, поэтому чтобы избежать / как \/). /id(\d{9}) - регулярное выражение для сопоставления. Имейте в виду, что разделитель !, поэтому / не является особенным, он просто соответствует буквальному /. Скобки образуют группу захвата, поэтому $1 будет числом. ! - это разделитель, за которым следует g, что означает совпадение столько раз, сколько возможно (в отличие от одного). Это то, что заставляет его подбирать все URL в строке, а не только первый. Пока есть совпадение, оператор m будет возвращать истинное значение, поэтому цикл будет продолжаться (и запускать этот say $1, распечатывая совпадение).

Раствор с двумя седлами

Я думаю это один из способов сделать это только с помощью sed. Гораздо сложнее!

echo 'junk jumk http://foo/id231313 junk lalala http://bar/id23123 asda' | \
    sed 's!http://!\nhttp://!g' | \
    sed 's!^.*/id\([0-9]*\).*$!\1!' 
0 голосов
/ 24 февраля 2011

Вот решение, использующее только один вызов sed:

sed -n 's| |\n|g;/^http/{s|http://[^/]*/id\([0-9]*\)|\1|;P};D' inputfile

Объяснение:

  • s| |\n|g; - Разделяй и властвуй
  • /^http/{ - Если пробел начинается с «http»
    • s|http://[^/]*/id\([0-9]*\)|\1|; - захватить идентификатор
    • P - Вывести строку, предшествующую первой новой строке
  • }; - конец, если
  • D - Удалить строку, предшествующую первой новой строке, независимо от того, содержит ли она «http»

Редактировать:

Эта версия использует ту же технику, но более избирательна.

sed -n 's|http://|\n&|g;/^\n*http/{s|\n*http://[^/]*/id\([0-9]*\)|\1\n|;P};D' inputfile
0 голосов
/ 24 февраля 2011

Проблема в том, что sed, grep и awk работают над строками, а у вас есть только одна строка.Таким образом, вам, вероятно, нужно разделить вещи, чтобы у вас было более одной строки - тогда вы можете заставить нормальные инструменты работать.

tr ':' '\012' < res |
sed -n 's%.*/\(id[0-9][0-9]*\).*%\1%p'

Это использует преимущества URL-адресов, содержащих двоеточия, и сопоставляет двоеточия с новыми строками с помощью tr, затем использует sed, чтобы взять что-либо до косой черты, затем id и одну или несколько цифр, после чего-либо, и выводит строку идентификатора и цифры (только).Поскольку они встречаются только в URL-адресах, они будут отображаться только по одному в каждой строке и относительно близко к началу строки.

0 голосов
/ 24 февраля 2011
cat res | perl -ne 'chomp; print "$1\n" if m/\/(id\d*)/'
...