如何使用 Linux 命令删除文件中子标题下的行

如何使用 Linux 命令删除文件中子标题下的行

我有一个如下文件。我想在其中单独删除特定子标题下的行。我尝试使用一些 sed 和 awk 命令,但无法得到它。任何人都可以帮忙用一些linux命令来破解这个问题吗?

[first attempt]
a=10
b=20

[second attempt]
a=20
b=20

[third attempt ] 
a=30
b=50

我想单独删除“[第二次尝试]”子标题下的行。输出应如下所示。我只想删除子标题下的内容,并且可以选择将删除的行替换为一个空行

[first attempt]
a=10
b=20

[second attempt]

[third attempt ] 
a=30
b=50

答案1

awk -v blkid=0 -v rmblk=2 '{
      if ( $1 ~ /^\[/) {
            blkid+=1;blkn=NR;print };
      if ( blkid !=rmblk && NR!=blkn )
            print ;
      else if(blkid ==rmblk && NF == 0)
                  print ""}' file.txt

每个块的 id 从 1 开始,每个块递增 1:blkid

您要删除的块的块 ID:rmblk

当第一个字段以 开头时,每个块将开始[

该变量blkn存储NR值[first attempt] [second attempt]等。

答案2

sed '$!N;/^\[second/,/^\n\[/P;D' <infile >outfile

这可能应该可以,尽管我不太清楚您想要如何处理下一部分之前的尾随空白行。此输出包含它,因为这似乎是正确的做法,但如果您只想从任何部分中删除最后一个空白行,这可以相对轻松地完成 - 所以只需询问即可。

!基本上,对于不是最后一个的每个输入行$sed也会拉入Next 行并将其附加到插入的\newline 字符分隔符之后的模式空间中。每次发生这种情况时,模式空间都会发生变化:

 ^Line1\nLine2$
 ^Line2\nLine3$
 ^Line3\nLine4$

如果当前模式空间与模式匹配^\[second或者^\n\[或这两者之间出现的任何行,sedP打印到\n模式空间中第一个出现的 ewline - 因此每次迭代只打印其缓冲区的一半。

最后,sed D删除\n模式空间中第一个出现的 ewline 并从顶部再次启动脚本 - 这就是我们获得移位效果的方式。这被称为滑动窗口。它工作得很好,而且速度相当快。


我想这个问题有多个版本之类的?不管怎样,走相反的路并不难,真的。

你可能会这样做...

sed -ne '/^\[[^s]/,/^\[s/p' <in >out

这只会打印不跟随以字符开头的标题的任何内容s,以及所有标题。不过,它并没有在之后执行整洁的小换行符:


[first attempt]
a=10
b=20

[second attempt]
[third attempt ]
a=30
b=50

如果你想更明确一点,你也可以这样做:

sed '/^\[[second]/P;$!N;//,/\n$/!P;D' <in >out

...这确实做了整洁的小换行...

[first attempt]
a=10
b=20

[second attempt]

[third attempt ]
a=30
b=50

所有这些都是sed范围,对于每个匹配表达式,如下所示:

/match1/,/match2/command

...sed将应用command到两个匹配的行以及之间的所有行。

答案3

您也可以使用简短的sed脚本来完成此操作。将以下内容放入文件中:

/second/ {
   n
   : del
   /./ ! b
   N
   s/.*\n//
   b del
}

叫它script。然后使用sed -f script myfile.如果您尝试就地编辑文件,请使用sed -i -f script myfile,但我建议您在尝试之前运行第一个命令,并确保它正是您想要的输出。

解释:

一旦找到该字符串second,sed 将查看下一行。如果该行不为空,则将其丢弃并查看文件中的下一行,直到找到空行。该空行和文件中的所有其他行都会被打印。 (除非有另一行包含字符串second,在这种情况下会重复该过程。)

(如果有人感兴趣的话我可以解释更多。)

答案4

我将尝试 grep 到“第二次尝试”和“第三次尝试”的两个行号,然后删除中间的任何内容。根据您的需要进行相应编辑。 :)

#getting line number for [second attempt]
line_num_second=$(grep -n "second attempt" yourfile.txt | cut -d : -f 1)

#getting line number for [third attempt]
line_num_third=$(grep -n "third attempt" yourfile.txt | cut -d : -f 1)

start=$(expr $line_num_second +1)
end=$(expr $line_num_third -2)

#removes the content in between [second attempt] and [third attempt]
sed $start,"$end"d yourfile.txt

# sed -i $start,"$end"d yourfile.txt # -i - overwite/edit your files in-place instead of printing to standard output

相关内容