目标
如何删除文本文件中匹配行之前的所有行,包括这一行?
输入文件示例:
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 进行管道传输并删除,直到那时。