如何仅使用sed删除文件中第一个出现的行

我有以下文件

titi tata toto tata 

如果我执行

 sed -i "/tat/d" file.txt 

它将删除所有包含tat的行。 该命令返回:

 titi toto 

但我只想删除包含tat的文件中出现的第一行:

 titi toto tata 

我怎样才能做到这一点?

Solutions Collecting From Web of "如何仅使用sed删除文件中第一个出现的行"

你可以使用两个地址的形式:

 sed '0,/tat/{/tat/d;}' inputfile 

这将删除模式的第一次出现。

info sed引用info sed

  A line number of `0' can be used in an address specification like `0,/REGEXP/' so that `sed' will try to match REGEXP in the first input line too. In other words, `0,/REGEXP/' is similar to `1,/REGEXP/', except that if ADDR2 matches the very first line of input the `0,/REGEXP/' form will consider it to end the range, whereas the `1,/REGEXP/' form will match the beginning of its range and hence make the range span up to the _second_ occurrence of the regular expression. 

如果你可以使用awk ,那么这使得它:

 $ awk '/tata/ && !f{f=1; next} 1' file titi toto tata 

要将结果保存在当前文件中,请执行

 awk '...' file > tmp_file && mv tmp_file file 

说明

让我们激活一个标志,每当tata第一次匹配,并跳过线。 从那一刻起,不要忽略这些线条。

  • /tata/匹配包含字符串tata
  • {f=1; next} {f=1; next}设置标志f为1,然后跳过该行。
  • !f{}如果标志f被设置,跳过这个块。
  • 1 ,作为True值,执行默认的awk操作: {print $0}

Tom Fenech的另一种方法

 awk '!/tata/ || f++' file 

|| 代表或,所以这个条件是真实的,因此打印行,每当这些发生:

  • tata不在行中。
  • f++是真的。 这是一个棘手的部分:第一次f是默认的0,所以第一个f++将返回False,而不是打印行。 从那一刻起,它将从一个整数值递增,并为真。

这是一个使用sed

 sed ':a;$!{N;ba};s/\ntat[^\n]*//' file titi toto tata 

以下是一般的做法:

 $ cat file 1 titi 2 tata 3 toto 4 tata 5 foo 6 tata 7 bar $ $ awk '/tat/{ if (++f == 1) next} 1' file 1 titi 3 toto 4 tata 5 foo 6 tata 7 bar $ $ awk '/tat/{ if (++f == 2) next} 1' file 1 titi 2 tata 3 toto 5 foo 6 tata 7 bar $ $ awk '/tat/{ if (++f ~ /^(1|2)$/) next} 1' file 1 titi 3 toto 5 foo 6 tata 7 bar 

请注意,通过上述方法,您可以跳过任何您喜欢的RE(第一,第二,第一和第二,无论)的事件,而且您只指定一次RE(而不必为了一些替代解决方案而复制它) 。

清晰,简单,明显,易于维护,可扩展等

这可能适用于你(GNU sed):

 sed '/pattern/{x;//!d;x}' file 

除了那些包含图案的线以外,打印所有行。 否则,如果行包含模式并且保留空间不是(第一次出现),则删除该行。

你可以找到第一个与grep匹配的行号,并把它传给sed删除。

 sed "$((grep -nm1 tat file.txt || echo 1000000000:) | cut -f 1 -d:) d" file.txt 

grep -n结合cut找到要删除的行号。 grep -m1确保至多找到一个行号。 echo处理匹配的情况,以便不返回空结果。 sed "[line number] d"删除行。