【问题标题】:Cannot understand a sed pattern无法理解 sed 模式
【发布时间】:2013-06-25 19:15:20
【问题描述】:

我最初的问题是能够在配置文件中特定块的末尾添加一行。

############
# MY BLOCK #
############
VALUE1 = XXXXX
VALUE2 = YYYYY
MYNEWVALUE = XXXXX      <<< I want to add this one

##############
# MY BLOCK 2 #
##############

为此,我使用了以下 sed 脚本,它可以完美运行(在另一篇文章中找到):

sed -i -e "/# MY BLOCK #/{:a;n;/^$/!ba;i\MYNEWVALUE = XXXXX" -e '}' myfile

这在 shell 脚本中执行时效果很好,但我无法直接在交互式 shell 中使用它(它给了我一个错误:“!ba event not found”)。为了解决这个问题,我尝试在 '!ba' 之前添加 '\' 但现在它给了我另一个错误,告诉我 '\' 是一个未知命令。

谁能解释我在上述问题上的错误在哪里以及这个脚本是如何工作的?

这是我的理解:

-i : insert new line (i think the first one is useless, am i right?)
-e : execute this sed script (don't understand why there is a second one at the end to close the })
:a : begin a loop
n : read each line with the pattern ^$ (empty lines)
! : reverse the loop
ba : end of the loop

谢谢!

【问题讨论】:

  • -i--in-place 的缩写(用修改后的内容替换输入文件),-e--expression 的缩写。阅读 man sed 会向您揭示(以及更多)。
  • 我做到了,谢谢你的回复。我只想知道 sed 是如何工作的,因为您可以看到我的 -i 和 -e 在 man 描述附近。

标签: bash loops sed block


【解决方案1】:

使用' 而不是" 以避免bash 尝试在! 上进行历史替换

如果XXXXX包含shell参数扩展或类似的,你可以这样做:

sed -i -e"/# $BLOCK_NAME"'#/{:a;n;/^$/!ba;i\'"$NEW_VAR = $NEW_VALUE" -e"}" myfile

需要第二个-e 才能有效地插入换行符以关闭i 命令。您实际上可以直接插入换行符:

sed -i -e"/# $BLOCK_NAME "'#/{:a;n;/^$/!ba;i\'"$NEW_VAR = $NEW_VALUE"$'\n}' myfile

【讨论】:

  • 我也不知道第二个 -e,我试过你的代码,它给了我“sed: -e expression #1, char 0: unmatched `{'”。使用第二个 -e 它可以完美运行,但我不知道为什么需要它。
  • @Arka:我又看了一遍,更新了我的答案。很抱歉造成混乱。
【解决方案2】:
  • :a 引入了一个标签,名为 a
  • n 将当前模式空间写入输出,并将模式空间替换为下一行输入。
  • /^$/! 表示匹配模式空间中 NOT (!) 空白行的行;以下ba 是匹配(非空行)发生时的“标记 a 的分支”。
  • 如果没有发生分支,则插入 i

在命令行中使用单引号 (') 而不是双引号 (") 以防止 shell 执行 shell 替换(包括“$”和“!”字符)。

【讨论】:

  • 感谢您的解释。对于“n”,当您的意思是它写入/替换模式时,它是否像“读取”一样?我的意思是你可以从一个简单的文件中读取行?
  • 是的:您正在写入当前的“缓冲区”(最后一行读取 + 更改,例如插入)并读取下一行输入。
【解决方案3】:

在交互式 shell 中,! 用于历史替换,因此您需要对其进行转义:

sed -i -e "/# MY BLOCK #/{:a;n;/^\$/\!ba;i\MYNEWVALUE = XXXXX" -e '}' myfile

您还应该转义$,因为它在双引号字符串中具有特殊含义(尽管在这种情况下没关系,因为它后面跟着/,而不是变量名)。

【讨论】:

    猜你喜欢
    • 2014-12-13
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2020-07-04
    • 1970-01-01
    相关资源
    最近更新 更多