我正在编写配置文件修改的脚本,如下所示:
[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 行 [紫色]