sed命令用两行内容替换一个空行

sed命令用两行内容替换一个空行

如何用两行内容替换第一个空行?我确实看到了一个问题在 vim sed 中用单个空行替换多个空行但不太明白如何适应这一点。因此,例如,如果我的输入文件是:

% abd
% def

% jkl

% mno

我想要一个 sed 命令来替换第一的包含这两行的空白行(一行包含ghi,另一行包含%):

% abd
% def
% ghi
%
% jkl

% mno

答案1

Sed 匹配整行,但不包括换行符,因此空行只是一个空字符串。您可以使用^来匹配行的开头和$结尾,从而^$匹配空行。只需将其替换为% ghi\n%

sed 's/^$/% ghi\n%/'

% ghi已经存在的换行符将保留,因此您最终会在一行和%下一行上结束


编辑:如果只需要匹配一次,那么表达式会稍微复杂一些。我知道的最简单的方法sed是:

sed '0,/^$/ s/^$/% ghi\n%/'

替换内容包含在地址范围中0,/^$/,这意味着“仅将以下内容应用于 0 和匹配的第一行之间的行^$”。由于替换表达式^$也会检查,因此唯一真正要更改的行是第一个匹配的行^$- 第一个空行

答案2

这是另一种方法,sed仅替换第一个空行而不\n使用右心轴或者gnu sed 0 个地址扩大:

sed '/^$/{      # if line is empty
x               # exchange pattern space w. hold space
//{             # if pattern space is empty (means the hold buffer was empty)
s//%/           # replace it with a % character
h               # overwrite hold space (so now hold space looks like this: ^%$)
s/$/ ghi/       # add a space and the string ghi after the %, then
G               # append content of hold buffer to pattern space so now the
}               # pattern space looks like this: ^% ghi\n%$
//!x            # if pattern space is not empty it means a change was
}               # already made so exchange back (do nothing)
' infile

一班轮:

sed -e'/^$/{x;//{s//%/;h;s/$/ ghi/;G' -e'}' -e'//!x' -e'}' infile

虽然说实话,这对于以下人来说是小菜一碟ed

ed -s infile <<< $'/^$/s//% ghi\\\n%/\n,p\nq'

替换,pw就地编辑文件。

答案3

注意:这回答了最初的问题,该问题要求:

如何用两行内容替换单个空行?

这并不能回答“变色龙”的问题。


sed '/^$/{i\
% ghi\
%
d
}'

sed找到空行时,插入两行“ % ghi”和“ %”,然后删除空行。


来自评论

这会产生语法错误。

使用真正的贝壳而不是贝壳;从长远来看,这将拯救每个人的悲伤。将命令放在一个简单文件的 5 行中并使用sed -f sed.script.在 C shell 中可能还有其他方法可以实现这一点 - 不过,这是可行的:

echo '/^$/{\'  > sed.script
echo '% ghi\' >> sed.script
echo '%'      >> sed.script
echo 'd'      >> sed.script
echo '}'      >> sed.script
sed -f sed.script data.file
rm -f sed.script

答案4

sed -e1\!b -e:n -e"/^$/c$(printf '\\\n%%%s' \ ghi '')" -en\;bn

sed理解将脚本化、固定字符串写入标准输出的三个原语。所有三个都在脚本中紧随其后的反斜杠转义换行符之后开始,并在脚本中第一个出现的未转义换行符或脚本中第一个出现的文件结尾处结束:

  • i

    • i将固定字符串插入到标准输出现在
  • a

    • a在下一个行周期之前,按照脚本发生的顺序,安排固定字符串追加到 stdout,或者,对于最后一行,在本行的末尾
  • c

    • 删除所有地址的模式空间[es](1(,2)?)?,结束当前行周期,并将c输出挂起到任何地址的最后一个的固定字符串[es]

printf '\n\n\n\n\n' |
sed -e1\!b -e:n \
    -e"/^$/c$(printf '\\\n%%%s' \ ghi '')" \
    -en\;bn

% 吉利
%




因此,此脚本会为不是stb的每一行延伸出脚本,但从第一行开始,直到它可以将空行挂到固定字符串为止,它会在用 ext 覆盖之前自动打印每个非空行并循环回到ext 标签以再次进行。!1cn:n

相关内容