如何在匹配后打印到文件末尾的所有行?

log*_*hee 71 grep sed text-processing

输入文件 1 是:

dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)

我给匹配的模式来自 in other file(比如dog 123 4335来自 file2)。

我匹配行的模式,dog 123 4335并且在打印没有匹配行的所有行后,我的输出是:

cat 13123 23424
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)

如果只使用无行地址只使用模式,例如1s 如何匹配和打印行?

bra*_*zzi 48

在实践中,我可能大部分时间都使用Aet3miirah 的答案,而alexey 的答案对于浏览线条非常棒(而且,它适用于less)。OTOH,我真的很喜欢另一种方法(这是一种颠倒的吉尔斯回答):

sed -n '/dog 123 4335/,$p'
Run Code Online (Sandbox Code Playgroud)

当使用-n标志调用时,sed默认情况下不再打印它处理的行。然后我们使用 2-address 形式,表示从匹配的行/dog 123 4335/到文件末尾(由 表示$)应用命令。有问题的命令是p,它打印当前行。所以,这意味着“打印从匹配/dog 123 4335/到结束的所有行”。

  • `sed -n'/dog 123 4335/,$p' | tail -n +2` 也将删除匹配项 (6认同)
  • 这会打印 `dog` 行,尽管这里不需要。 (5认同)
  • 这看起来是最好的答案(并且适用于我自己的情况),但也需要进行调整以跳过匹配的行。 (3认同)
  • sed -n '/dog 123 4335/,$p' | sed '1d' 将删除狗线 (3认同)
  • 快速说明:`-n` 表示不打印已处理的行,`/pattern/` 位于正斜杠 `/` 内,`$` 表示结束,`p` 表示打印 (2认同)

Tho*_*hor 35

假设您想将整行与您的模式匹配,使用 GNU sed,这有效:

sed -n '/^dog 123 4335$/ { :a; n; p; ba; }' infile
Run Code Online (Sandbox Code Playgroud)

标准等效:

sed -ne '/^dog 123 4335$/{:a' -e 'n;p;ba' -e '}' infile
Run Code Online (Sandbox Code Playgroud)

使用以下输入 ( infile):

cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)

输出是:

cat 13123 23424 
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)

解释:

  • /^dog 123 4335$/ 搜索所需的模式。
  • :a; n; p; ba;是一个循环,它从输入 ( n)中获取一个新行,打印它 ( p),然后分支回到标签 a :a; ...; ba;

更新

这是一个更接近您需求的答案,即文件 2 中的模式,从文件 1 中 grepping:

tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1
Run Code Online (Sandbox Code Playgroud)

嵌入的 grep 和 cut 从文件 2 中找到包含模式的第一行,此行号加一传递到尾部,加一用于跳过具有模式的行。

如果您想从最后一场比赛而不是第一场比赛开始,它将是:

tail -n +$(( 1 + $(grep -n -f file2 file1 | tail -n1 | cut -d: -f1) )) file1
Run Code Online (Sandbox Code Playgroud)

请注意,并非所有版本的 tail 都支持加号。


小智 33

如果您有一个相当短的文件grep可能会起作用:

grep -A5000 -m1 -e 'dog 123 4335' animals.txt
Run Code Online (Sandbox Code Playgroud)

5000 只是我对“合理短”的猜测,因为grep找到第一个匹配项并将其与接下来的 5000 行一起输出(文件不需要那么多)。如果您不想要匹配本身,则需要将其切断,例如

grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2
Run Code Online (Sandbox Code Playgroud)


如果你不想要第一个,但最后一个匹配作为分隔符,你可以使用这个:

tac animals.txt | sed -e '/dog 123 4335/q' | tac
Run Code Online (Sandbox Code Playgroud)

该行animals.txt以行的相反顺序读取并输出直到并包括行,dog 123 4335然后再次反转以恢复正确的顺序。

同样,如果您不需要结果中的匹配项,请附加尾部。(您也可以使 sed 表达式复杂化以在退出之前丢弃其缓冲区。)


Gil*_*il' 17

sed -e '1,/dog 123 4335/d' file1
Run Code Online (Sandbox Code Playgroud)

如果您需要从文件中读取模式,请将其替换为 sed 命令。如果文件包含 sed 模式:

sed -e "1,/$(cat file2)/d" file1
Run Code Online (Sandbox Code Playgroud)

如果文件包含要查找的文字字符串,请引用所有特殊字符。我假设该文件包含一行。

sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1
Run Code Online (Sandbox Code Playgroud)

如果您希望匹配是整行,而不仅仅是子字符串,请将模式包装在^…$.

sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1
Run Code Online (Sandbox Code Playgroud)

  • 如果模式在第一行,那将不起作用。GNU `sed` 有 `0,/dog.../d`。 (6认同)

小智 15

$ more +/"dog 123 4335" file1

  • 它也适用于 `less`。 (5认同)
  • 在终端上很聪明,但如果你把它用管道输送到其他东西,比如`tac`,它实际上不起作用。 (4认同)

Sté*_*las 11

awk

awk 'BEGIN {getline pattern < "other file"}
   NR == 1, $0 ~ pattern {next}; {print}' < "input file"
Run Code Online (Sandbox Code Playgroud)


mik*_*erv 6

如果输入是一个lseekable常规文件:

使用 GNU grep

{ grep  -xFm1 'dog 123 4335' >&2
  cat; } <infile 2>/dev/null >outfile
Run Code Online (Sandbox Code Playgroud)

sed

{ sed -n '/^dog 123 4335$/q'
  cat; } <infile >outfile
Run Code Online (Sandbox Code Playgroud)

grep带有该-m选项的GNU将在匹配时退出输入 - 它会在找到最后一个匹配点后立即离开其(lseekable)输入 fd。因此,调用grepw/ 会-m1在文件中找到模式的第一次出现,并将输入偏移量保留在正确的位置,cat以便将文件中模式第一次匹配之后的所有内容写入标准输出。

即使没有 GNU,grep您也可以在兼容 POSIX 的情况下做完全相同的事情sed- 当sed q它被指定将其输入偏移量保留在正确位置时。但是,GNUsed不符合标准,因此,sed除非您使用其-u开关调用它,否则上述内容可能无法与 GNU一起使用。


Gur*_*uru 5

使用 awk 的一种方式:

awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}'  file2 file1
Run Code Online (Sandbox Code Playgroud)

其中 file2 包含您的搜索模式。首先,file2 的所有内容都存储在数组“a”中。处理 file1 时,会根据数组检查每一行,并仅在不存在时打印。


小智 5

我对主题中问题的回答,没有将模式存储在第二个文件中。这是我的测试文件:

$ cat animals.txt 
cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)

GNU sed:

 $ sed '0,/^dog 123 4335$/d' animals.txt 
 cat 13123 23424 
 deer 2131 213132
 bear 2313 21313
Run Code Online (Sandbox Code Playgroud)

珀尔:

$ perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313
Run Code Online (Sandbox Code Playgroud)

文件中带有模式的 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
Run Code Online (Sandbox Code Playgroud)


Jef*_*ler 5

重量ed

ed -s file1 <<< '/dog 123 4335/+1,$p'
Run Code Online (Sandbox Code Playgroud)

这会p在此处字符串中向 ed 发送一个 rint 命令;打印命令的范围限制为( )匹配后的1到文件末尾 ( )。+1dog 123 4335$