使用 sed 在两个空行之前插入文本

使用 sed 在两个空行之前插入文本

我正在尝试使用 sed 来更新带注释的配置文件。我并没有将所有内容都放在 EOF 处,而是尝试将所有内容分开。我的配置看起来像这样。

# SECTION ONE
data...
data...
data...
<insert line here>

# SECTION TWO
data...
data...

我试图在第一节的末尾插入行,但我很难编写搜索模式,因为它不允许“\n”,并且模式中不能有多个“^$” 。我想要如下的东西:

sed -i "/^\n\n# SECTION TWO.*/i data..." somefile.conf

    or

sed -i "/^$^$# SECTION TWO.*/i data..." somefile.conf

我也愿意接受其他建议,但如果可能的话,我想将其保留在一行中。这是一个更大的脚本的一部分。我知道使用 Python、Perl 等非常容易,但我试图将其保留为“shell”解决方案。

答案1

使用awk代替sed

newdata='This is the new data'

newdata=$newdata awk -F '\n' -v OFS='\n' -v RS= -v ORS='\n\n' \
    '$1 == "# SECTION ONE" { $(NF+1) = ENVIRON["newdata"] }; 1' file

或者

newdata='This is the new data'

newdata=$newdata awk '
    BEGIN { FS = OFS = "\n"; RS = ""; ORS = "\n\n" }
    $1 == "# SECTION ONE" { $(NF+1) = ENVIRON["newdata"] }; 1' file

这通过使用输入记录分隔符awk的空值来进入“段落阅读模式” 。RS这意味着awk一次将阅读一个段落。 “段落”是由至少一个空行分隔的任何行的集合。

然后,我们将输入字段分隔符FS设为换行符,-F '\n'以便段落中的每一行都成为其自己的字段。

我们还设置了与输出相关的相应变量ORSOFS使得记录(段落)以尾随空行输出,字段(段落内的行)以换行符结束输出。

实际代码检测段落的第一行何时正是字符串# SECTION ONE。如果是这种情况,则会将新字段添加到包含新数据的当前记录的末尾。新数据取自newdata环境变量。

所有段落,无论是否修改,都会无条件输出。

请注意,如果实际的配置文件(我们在问题中从未看到)是用 XML、YAML、JSON 或其他结构化文档格式编写的,那么答案是无效的,如那些文档格式要求用于读取和写入的正确格式感知工具(因为它们不是面向行的并且数据需要编码/解码)。

答案2

使用 GNU sed 我们可以执行以下操作:

sed -e '/# SECTION ONE/,/^$/s/^$/__NEW-DATA__\n/' file

awk 中的范围运算符可用于获得所需的输出

awk '
  /# SECTION ONE/,!NF{
    if (!NF) print "__NEW-DATA__"
  }1
' file

此方法使用 POSIXly sed 构造

sed -e '
  /# SECTION ONE/!b
  :a
    n;/^$/!ba
  G;s/^/__NEW-DATA__/
' file

在此方法中,我们将新数据放置在节名称之前,前提是它不是第一个数据。假设文件大小至少为 3 行。

sed -e '
  1,2N
  $q;N
  s/^\n\n# SECTION TWO/__NEW-DATA__\n&/;t
  P;D
' file

答案3

再次阅读Kusalandras的评论和问题后,我像他或她一样理解它。

GNU-sed 有一个打开 POSIX 风格的开关,所以我希望这次该命令与 sed 风格无关。

原始文件:

cat FILE
# SECTION ONE
data...
data...
data...

# SECTION TWO
data...
data...

命令:

sed --posix "s/^[ \t]*$/...new data .../; /# SECTION TWO/i\\ " FILE

# SECTION ONE
data...
data...
data...
...new data ...
 
# SECTION TWO
data...
data...

请注意,插入会在文件中留下空白,可以使用后续 sed 命令将其删除,也可以通过 useinds/^[ \t]*$作为正则表达式来处理,它匹配空行以及空白和/或制表符的纯空白。

选择:

sed --posix "s/^$/...new data .../; /# SECTION TWO/i\ " -e "s/^ $//" FILE 

第二种形式使用第二个 sed 命令(-e - 可以说,它是第三个,在使用两个命令之后,;在第一个引号中分隔)来删除空格(如果不能容忍),因此在查找空行时是教条的。

相关内容