Regex sed:在块后追加

Regex sed:在块后追加,regex,sed,append,Regex,Sed,Append,我对sed很陌生,我发现的一切都有点像这里,有点像那里 我有一个文本文件,其中包含如下所示的块: #start a b c #whatever … sed -n '/^#\s*start/,/^$/ p' data.txt 显然,这是一个简化的版本。我想在#start块的末尾追加一行,以提供: #start a b c d #whatever … 我可以通过以下方式找到该块: #start a b c #whatever … sed -n '/^#\s*start/,/^$/

我对sed很陌生,我发现的一切都有点像这里,有点像那里

我有一个文本文件,其中包含如下所示的块:

#start
a
b
c


#whatever
…
sed -n '/^#\s*start/,/^$/ p' data.txt
显然,这是一个简化的版本。我想在
#start
块的末尾追加一行,以提供:

#start
a
b
c
d

#whatever
…
我可以通过以下方式找到该块:

#start
a
b
c


#whatever
…
sed -n '/^#\s*start/,/^$/ p' data.txt
所以我认为这是正确的方向。然而:

  • 所选内容包括我不想要的空行
  • 我不知道比赛结束后如何再加一行

对于GNU-sed,请尝试此选项(再次更新,有一个小错误):

例如:

sed
命令将洗牌那些
不太空的
空行(仅空格行)。但我想这对你来说没关系,对吧?
想法是使用
保留空格
来保留需要追加的内容(
d
),并在时机成熟时追加。
x
是将
保持空间
模式空间
(当前读取行)交换


顺便说一句,如果有多个
#start
块,它将附加到所有块中,如果您不希望出现这种行为,请发表评论。

您可以使用
awk
非常简单:

awk -v RS= '/#start/{$0 = $0 ORS "d\n"} 1' file
如果
#start
不在文件顶部,则您需要执行以下操作:

awk -v RS= '/#start/{$0 = $0 ORS "d"} {$0 = $0 ORS} 1' file
*这将删除每个块之间除一个换行外的所有换行

结果

#start
a
b
c
d

#whatever
…
对于sed:

sed '/#start/,/^$/ s/^$/d/;' file
  • /#start/,/^$/
    :搜索以
    #start
    开头并以空行结尾的块
  • s/^$/d/
    :将匹配的空行替换为
    d
如果要在空白行之前添加字符串:

sed '/#start/,/^$/{/^$/{s//d/;G;};}' file
这可能适用于您(GNU-sed):

关注行首
#start
和空行之间的行范围。如果该行为空,请将其更改为a
d

注意,
否定匹配,
b
不带占位符,将退出sed的任何进一步处理

为了进行比较,请注意这些解决方案的行为,在第一种情况下,在空行前插入
d
,在第二种情况下,在空行后追加
d

sed '/^#start/,/^\s*$/!b;/^\s*$/i\d' file

sed '/^#start/,/^\s*$/!b;/^\s*$/a\d' file

在任何UNIX设备上的任何shell中使用任何awk:

$ awk 'BEGIN{RS=""; ORS="\n\n"; FS=OFS="\n"} $1=="#start"{$(NF+1)="d"} 1' file
#start
a
b
c
d

#whatever
…

与当前接受的sed解决方案不同,即使目标字符串包含regexp元字符,即使要添加的字符串包含反向引用,即使其中任何一个包含分隔符(
/
),上述解决方案也可以工作,并且可以根据第二、第三、第三个,或者输入块的任何其他行,而不仅仅是第一行,它可以被简单地修改,以添加或修改块中间的任何行。简而言之,这是一种非常优越的方法。

区块本身不会有任何缺口。块后可能有多个换行符。@Tiw GNU sed version 4.2.1可能需要
i
command
sed-e'/#start/,/^$/{/^$/i\d'-e'}data.txt
也许我想得太多了,但你没有连续的块,之间没有空行?这不是正确的方向。sed是在各行上执行s/old/new的正确工具,但仅此而已-对于其他任何东西,您都应该使用其他工具,以获得更清晰、更简单、更健壮、更便携和更高效的结果。谢谢,这项工作做得很好,而且对我来说足够简单。作为一个附加的问题,在空白行之前插入新行是可能的吗?否则,它会耗尽空白行,我很快就会用完它们……我编辑了我的答案。您可以使用
G
命令执行此操作,该命令将在已替换为
d
@SLePort>的命令后插入一个空行。再次感谢。
$ awk 'BEGIN{RS=""; ORS="\n\n"; FS=OFS="\n"} $1=="#start"{$(NF+1)="d"} 1' file
#start
a
b
c
d

#whatever
…