grep +A: распечатать все после матча
Привет у меня есть файл, содержащий список URL-адресов, выглядит следующим образом:
file1:
http://www.google.com
http://www.bing.com
http://www.yahoo.com
http://www.baidu.com
http://www.yandex.com
....
Я хочу получить все записи после: http://www.yahoo.com/, результаты выглядят так:
file2:
http://www.baidu.com
http://www.yandex.com
....
Я знаю, что могу использовать grep, чтобы найти номер строки, где лежит yahoo.com, используя
$grep -n 'http://www.yahoo.com' file1
3 http://www.yahoo.com
Но я не знаю, как получить файл после строки № 3. Кроме того, я знаю, что в grep есть флаг -A выводить строки после вашего совпадения. Однако вам нужно указать, сколько строк вы хотите после матча. Мне интересно, есть ли что-то, чтобы обойти эту проблему. Подобно:
PSEUDO CODE:
$ grep -n 'http://www.yahoo.com' -A all file1 > file2
Я знаю, что мы могли бы использовать номер строки, который я получил, и wc -l, чтобы получить количество строк после yahoo.com, однако... кажется довольно слабым.
Надеемся на удобное и простое решение. Не стесняйтесь критиковать меня за усложнение проблемы в самом начале, и команды awk и sed также приветствуются!
5 ответов
Awk
Если вы не возражаете против использования awk:
awk '/yahoo/{y=1;next}y' data.txt
Этот скрипт состоит из двух частей:
/yahoo/ { y = 1; next }
y
Первая часть утверждает, что если мы встречаем строку с yahoo, мы устанавливаем переменную y=1, затем пропускаем эту строку (next
команда перейдет к следующей строке, пропуская дальнейшую обработку текущей строки). Без next
Команда, строка Yahoo будет напечатана.
Вторая часть - это короткая рука для:
y != 0 { print }
Это означает, что для каждой строки, если переменная y отлична от нуля, мы печатаем эту строку. В awk, если вы ссылаетесь на переменную, эта переменная будет создана и будет либо нулевой, либо пустой строкой, в зависимости от контекста. До встречи с yahoo переменная y равна 0, поэтому скрипт ничего не печатает. После встречи yahoo, y равен 1, поэтому каждая строка после этого будет напечатана.
Sed
Или, используя sed, следующее удалит все, вплоть до строки с yahoo:
sed '1,/yahoo/d' data.txt
Это намного проще сделать с sed
чем grep
, sed
может применять любую из однобуквенных команд для широкого диапазона строк; общий синтаксис для этого
START , STOP COMMAND
кроме как без пробелов. START
а также STOP
каждый может быть числом (означающим "номер строки N", начиная с 1); знак доллара (означающий "конец файла") или регулярное выражение, заключенное в косые черты, что означает "первая строка, соответствующая этому регулярному выражению". (Точные правила немного сложнее; GNU sed
Руководство имеет более подробную информацию.)
Итак, вы можете делать то, что вы хотите, так:
sed -n -e '/http:\/\/www\.yahoo\.com/,$p' file1 > file2
-n
означает "ничего не печатать, если специально не сказано", и -e
директива означает "с первого появления строки, которая соответствует регулярному выражению /http:\/\/www\.yahoo\.com/
в конец файла, p
ечать ".
Это будет включать строку с http://www.yahoo.com/
на это в выводе. Если вы хотите все после этой точки, но не в самой строке, самый простой способ сделать это - инвертировать операцию:
sed -e '1,/http:\/\/www\.yahoo\.com/d' file1 > file2
что означает "для строки 1 до первой строки, соответствующей регулярному выражению /http:\/\/www\.yahoo\.com/
, d
выбрать строку " (а затем, неявно, напечатать все остальное; обратите внимание, что -n
не используется в этот раз).
awk '/yahoo/ ? c++ : c' file1
Или в гольф
awk '/yahoo/?c++:c' file1
Результат
http://www.baidu.com http://www.yandex.com
Это легче всего сделать в Perl:
perl -ne 'print unless 1 .. m(http://www\.yahoo\.com)' file
Другими словами, выведите все строки, которые не находятся между строкой 1 и первым появлением этого шаблона.
Используя скрипт
#get index of yahoo word
index=`grep -n "yahoo" filepath | cut -d':' -f1`
#get total number of lines in file
totallines=`wc -l filepath | cut -d' ' -f1`
#subtract totallines with index
result=`expr $total - $index`
#gives the desired output
grep -A $result "yahoo" filepath