繁体   English   中英

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

[英]How to remove only the first occurrence of a line in a file using sed

我有以下文件

titi
tata
toto
tata

如果我执行

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

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

titi
toto

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

titi
toto
tata

我怎样才能做到这一点?

您可以使用双地址格式:

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

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

引自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

|| 代表OR,所以这个条件是真的,因此每当发生任何这些情况时都会打印该行:

  • tata没有找到。
  • f++是真的。 这是一个棘手的部分:第一次f默认为0,所以第一个f++将返回False而不打印该行。 从那一刻起,它将从整数值开始增加,并且将为True。

以下是使用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的任何事件(第1,第2,第1和第2,无论如何),并且您只指定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 -ncut结合查找要删除的行号。 grep -m1确保最多找到一个行号。 echo在没有匹配时处理大小写,以便不返回空结果。 sed "[line number] d"删除该行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM