whereis git
и Вы получаете путь к команде.
это просто, если мерзавец находится в Вас, СОЕДИНЯЮТ переменную каналом, в случае, если Вы установили ее не через Вас диспетчер пакетов, это более сложно, и необходимо использовать find
или locate
команды.
Принятие Вас хочет соответствовать целой строке Вашему шаблону GNU sed
, это работает:
sed -n '/^dog 123 4335$/ { :a; n; p; ba; }' infile
Стандартный эквивалент:
sed -ne '/^dog 123 4335$/{:a' -e 'n;p;ba' -e '}' infile
Со следующим входом (infile
):
cat 13123 23424
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
Вывод:
cat 13123 23424
deer 2131 213132
bear 2313 21313
/^dog 123 4335$/
поиски желаемого шаблона.:a; n; p; ba;
цикл, который выбирает новую строку от входа (n
), печатает его (p
), и ответвления назад к маркировке a :a; ...; ba;
.Вот ответ, который прибывает ближе в Ваши потребности, т.е. шаблон в file2, держа от file1:
tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1
Встроенный grep и сокращение находят первую строку, содержащую шаблон от file2, этого номера строки плюс, каждый передается хвосту, плюс каждый там для пропуска строки с шаблоном.
Если бы Вы хотите начать с последнего соответствия вместо первого соответствия, это было бы:
tail -n +$(( 1 + $(grep -n -f file2 file1 | tail -n1 | cut -d: -f1) )) file1
Обратите внимание, что не все версии хвоста поддерживают плюс нотация.
sed -e '1,/dog 123 4335/d' file1
Если необходимо считать шаблон из файла, заменить им в команду sed. Если файл содержит sed шаблон:
sed -e "1,/$(cat file2)/d" file1
Если файл содержит литеральную строку для поиска, заключите все специальные символы в кавычки. Я предполагаю, что файл содержит одну строку.
sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1
Если Вы хотите, чтобы соответствие было целой строкой, не только подстрокой, перенести шаблон в ^…$
.
sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1
sed
имеет 0,/dog.../d
для этого.
– Stéphane Chazelas
10.06.2015, 12:48
Один способ использовать awk:
awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}' file2 file1
где file2 содержит Ваши шаблоны поиска. Во-первых, все содержание file2 хранится в массиве "a". Когда file1 обрабатывается, каждая строка проверяется по массиву и печатается, только если не присутствует.
Так как awk явно не запрещен, вот мое предлагающее предположение, что 'кошка' является соответствием.
awk '$0 ~ /cat/ { vart = NR }{ arr[NR]=$0 } END { for (i = vart; i<=NR ; i++) print arr[i] }' animals.txt
tac
.
– jcomeau_ictx
02.07.2015, 09:25
+
был заменен -p
в POSIX 7: pubs.opengroup.org/onlinepubs/9699919799/utilities/more.html, но еще реализованный в util-linux 2.20.1. И это также печатает skipping..
и некоторые дополнительные новые строки (к stderr, который я ожидаю, так мог бы быть прекрасным).
– Ciro Santilli 新疆改造中心法轮功六四事件
14.09.2016, 15:41
Если у вас достаточно короткий файл grep
, может сработать:
grep -A5000 -m1 -e 'dog 123 4335' animals.txt
5000 - это просто моя догадка на "достаточно короткий", так как grep
находит первое совпадение и выводит его вместе со следующими 5000 строками (файл не должен иметь столько строк). Если вы не хотите, чтобы это совпадение совпадало само по себе, то вам придется его отсечь, например,
grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2
tac animals.txt | sed -e '/dog 123 4335/q' | tac
Эта строка читает animals.txt
в обратном порядке и выводит до строки с собакой 123 4335
включительно, а затем снова поворачивает в обратную сторону, чтобы восстановить правильный порядок.
Снова, если вам не нужно совпадение в результате, добавьте хвост. (Вы также можете усложнить выражение sed, чтобы отбросить его буфер перед выходом)
.Мой ответ на вопрос в теме, без хранения шаблона во втором файле. Вот мой тестовый файл:
$ cat animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
GNU SED:
$ sed '0,/^dog 123 4335$/d' animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
Perl:
$ perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
Вариант Perl с рисунком в файле:
$ cat pattern.txt
dog 123 4335
$ perl -ne 'BEGIN{chomp($p=(<STDIN>)[0])};print unless 1../$p/;' animals.txt < pattern.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
На практике я, вероятно, большую часть времени использовал бы ответ Aet3miirah, и alexey's answer замечательно подходит для навигации по линиям (также, он работает с less
)). ОТОХ, мне действительно нравится другой подход (который является своего рода обратным ответом Жиля :
sed -n '/dog 123 4335/,$p'
При вызове с флагом -n
, sed
по умолчанию больше не печатает строки, которые он обрабатывает. Затем мы используем 2-адресную форму, которая говорит о применении команды из строки, соответствующей /dog 123 4335/
до конца файла (представленного флагом $
). Данная команда представляет собой p
, которая печатает текущую строку. Таким образом, это означает "распечатать все строки из одной, соответствующей /дога 123 4335/
до конца"
с awk
:
awk 'BEGIN {getline pattern < "other file"}
NR == 1, $0 ~ pattern {next}; {print}' < "input file"
Если на входе lseekable обычный файл:
С GNU grep
:
{ grep -xFm1 'dog 123 4335' >&2
cat; } <infile 2>/dev/null >outfile
С sed
:
{ sed -n '/^dog 123 4335$/q'
cat; } <infile >outfile
GNU grep
, вызываемый с параметром -m
, прекращает ввод при совпадении - и оставляет свой (lseekable) введите fd сразу после точки, в которой было найдено последнее совпадение. Таким образом, вызов grep
w / -m1
находит первое вхождение шаблона в файл и оставляет входное смещение точно в нужном месте, чтобы cat
мог записать все, что следует за первым совпадением шаблона в файле, на стандартный вывод.
Даже без GNU grep
вы можете сделать то же самое с POSIX-совместимым sed
- когда sed
q
uit указано, чтобы оставить его входное смещение там, где оно есть. Однако GNU sed
не соответствует стандартам, поэтому приведенное выше, скорее всего, не будет работать с GNU sed
, если вы не вызовете его с помощью его -u
переключатель.
Как вывести все строки после совпадения до конца файла?
По-другому это можно сформулировать так: "Как удалить все строки от 1-й до совпадения (включая)", и это можно sed
-записать так:
sed -e '1,/MATCH PATTERN/d'
Если вы не возражаете против создания временного файла и у вас есть csplit
, это работает:
sh -c 'csplit -sf"$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2
Примечание file1
— входной файл, а file2
— файл шаблона (, как указано в вопросе ).
Длинная форма приведенной выше команды::
sh -c 'csplit --quiet --prefix="$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2
т. е.
csplit --quiet --prefix="file1_" "file1" "%^$(cat "file2")%+1" && cat "file1_00"
csplit
без приведенного выше флага prefix
создаст файлxx00
(с префиксом xx
и суффиксом00
). С указанным выше флагом создается файл file1_00
. Без флага quiet
он печатает размер выходного файла (размера результирующего файла ).