sed:删除匹配行之前的所有行,包括这一行

sed:删除匹配行之前的所有行,包括这一行

目标

如何删除文本文件中匹配行之前的所有行,包括这一行?

输入文件示例:

apple
pear
banana
HI_THERE
lemon
coconut
orange

期望的输出:

lemon
coconut
orange

目的是在 sed 中使用“-i”选项(直接编辑)。

干净的解决方案?

大多数类似问题的答案都提出了类似的内容:

sed -n '/HI_THERE/,$p' input_file

但匹配的行没有被删除:

HI_THERE
lemon
coconut
orange

然后,知道这一点将删除从匹配行(包括它)到文件末尾的所有内容:

sed '/HI_THERE/,$d' input_file

我尝试过这样的事情:

sed '^,/HI_THERE/d' input_file

但随后 sed 抱怨道:

sed: -e expression #1, char 1: unknown command: `^'

脏溶液

最后一个(肮脏的)解决方案是使用管道:

sed -n '/HI_THERE/,$p' input_file | tail -n +2

但是,直接编辑文件不起作用:

sed -n '/HI_THERE/,$p' input_file | tail -n +2 > input_file
cat input_file # returns nothing

并且必须使用这样的临时文件......

sed -n '/HI_THERE/,$p' input_file | tail -n +2 > tmp_file
mv tmp_file input_file

答案1

类似于您的“干净的解决方案”:

sed -e '1,/HI_THERE/d' input_file

文件中的第一行是第 1 行 - 没有特殊^地址,因为您总是知道这一点,而$结尾需要 while ,因为您(必然)不知道那是哪一行。

如果匹配线是第一的文件的行。使用 GNU sed,您可以使用0而不是1来处理这个问题。对于 POSIX sed 和可移植性(在本例中似乎有所不同),它更复杂(请参阅下面的评论和这个后续问题)。

答案2

如果你想坚持使用 Posix sed 你可以使用这个:

sed -ne '
  /HI_THERE/!d
  :loop
    n
    p
  bloop
' inp.file

或者,以简洁的方式写成:

sed -n '/HI_THERE/!d;:a;n;p;ba' inp.file

答案3

$ perl -ne 'print if 1 <(/HI_THERE/...eof)' input_file

我们使用范围运算符...来形成适当的范围,并进一步限制它拒绝所选范围内的第一个元素。

答案4

grep -nw HI_THERE file.txt |awk -F":" '{print $1}' | xargs -I % sed '1,%d' file.txt

解释:我使用精确的 word grep w,获取行号n
接下来,我使用 awk 提取行号,分隔符是:
进一步我使用 xargs 进行管道传输并删除,直到那时。

相关内容