匹配模式并替换其后面的第一个字符串实例

匹配模式并替换其后面的第一个字符串实例

我正在编写配置文件修改的脚本,如下所示:

[purple]
auth = no
enabled = 0
username = 
password =
priority = 0
host = True

[shovel]
group = 
manual = False
enabled = 0
username = 

其中有许多[类别],有时具有键/值对的相同键。

是否可以使用 awk/sed/grep/tr/cut/perl 制作一个单行程序,将“enabled = 0”的值更改为“enabled = 1”,但仅针对类别 [shovel]?

答案1

sed可以使用范围(停在类别末尾的空行上[shovel]):

sed '/\[shovel\]/,/^$/ s/enabled = 0/enabled = 1/' file

第一部分/\[shovel\]/,/^$/意味着找到带有 的行[shovel],继续前进,直到找到空行,然后s/old/new仅在该部分执行以下命令(在本例中为简单的 )file

请注意回应评论:sed不会接受范围和地址中的替代分隔符(因此,/如果需要匹配它们,请转义任何必须是文字的字符),除非它们前面有反斜杠。您始终可以在以下任何命令中使用替代分隔符,例如:

sed '/\[shovel\]/,/^$/ s|enabled = 0|enabled = 1|' file

或者

sed '\|\[shovel\]|, |^$| s|enabled = 0|enabled = 1|' file

答案2

这是使用 Perl 的解决方案,假设您的配置位于config.ini

perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^\[shovel\]\n/; print;' config.ini

这会执行以下操作:

  • -000$/ = "\n\n";- 以段落模式读取文件,与代码中的操作基本相同。
  • -n- 在循环内运行指定的代码while (<>) { }
  • -i- 内联编辑指定文件而不是打印到标准输出。您可以选择指定扩展名,这将导致使用该扩展名备份输入文件。例如,-i.bak将创建一个名为config.ini.bak.
  • -e- 执行指定的perl代码。

代码本身表示,如果输入“段落”本身在一行上开头,则替换enabled = 0包含完全相同的行。和必须转义,因为它们通常在正则表达式中具有特殊含义。enabled = 1[shovel][]

答案3

你可以尝试这个 awk 解决方案吗

awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input

答案4

您可以限制sed只修改特定行:

 sed -i '3s/enabled = 0/enabled = 1/g' file

这只会修改第 3 行 [紫色]

相关内容