所以我有一个像这样的文件
[ABC]
value1=bla
value2=bla
value3=bla
[XYZ]
value1=bla
value2=bla
value3=bla
我想用“value1=notbla”替换 [ABC] 块下的 value1,而不是 [XYZ] 块下的 value1。我已经尝试过了
sed '/ABC/{n;s/.*/change/}' file
但这仅在尝试转到下一行时有效,并且不会更改特定模式(即,如果 value1 低于值 2) 如果我不知道特定行号,我可以使用什么 sed 或 awk 命令。您能否标出所使用的每个 sed 或 awk 标签的功能。我真的很感激。
答案1
sed 可以很容易地处理这个问题。这是一个单一的“替代”命令,以地址范围为前缀。我添加了额外的间距以提高可读性:
sed -e '/^\[ABC\]$/ , /^\[.*\]$/ s/^\(value1=\).*$/\1notbla/'
没有额外的间距,它是:
sed -e '/^\[ABC\]$/,/^\[.*\]$/s/^\(value1=\).*$/\1notbla/'
您实际上并不需要锚定正则表达式,但在某些异常输入的情况下它们可能更安全。带有未锚定正则表达式的稍微较短的版本是:
sed -e '/\[ABC\]/,/^\[/s/^\(value1=\).*$/\1notbla/'
解释:
您要求对每个标志或选项进行解释,我有时间,所以您开始吧。我正在解释上面列出的三个 Sed 命令中的最终(最短)版本。
该行的第一部分是地址范围:地址范围后面的 ubstitute/startregex/,/stopregex/
命令s
仅适用于从startregex
到stopregex
(含)的行。
在这种情况下,起始正则表达式是/\[ABC\]/
.方括号通常是正则表达式中的特殊字符,因此我们在每个字符之前添加反斜杠来表示文字方括号字符。
停止正则表达式是/^\[/
,它使用特殊的正则表达式字符^
来表示行的开头。此模式将匹配任何以左方括号 ( [
) 开头的行。
替代命令s
基本上非常简单;一般格式是s/findregex/replacetext/
.它还可以在 Final 之后放置特殊标志/
来修改其行为,但我在这里没有使用任何此类标志。
“查找正则表达式”是^\(value1=\).*$
.
^
如前所述,插入符号 ( ) 匹配行的开头,而美元符号 ( $
) 匹配行的结尾。因此,整个模式必须匹配整行,而不仅仅是一行的一部分。
()
与方括号不同,括号 ( ) 是非-special 在正则表达式中默认是特殊的,所以我们在它们前面加上反斜杠来赋予它们特殊的含义。它们允许在替换文本中使用部分匹配文本(与“查找正则表达式”匹配的文本)。具体来说,\1
替换文本中的 表示“在正则表达式中第一组括号内匹配的文本”。在这种情况下,始终只是“value1=”。
“查找正则表达式”中的最后一个元素是.*
。点 ( .
) 表示“任何单个字符”,星号 ( *
) 表示“任意次数(零次或多次)”。因此,点星号 ( .*
) 与等号之后的该行的整个其余部分相匹配。
替换文本中的“notbla”只是静态文本,没有什么特别的。
要真正正确地学习 Sed,我强烈推荐Grymoire Sed 教程,这是免费的在线。
答案2
awk '
BEGIN {FS=OFS="=";}
/\[.*\]/ {if ($0 == "[ABC]") edit=1; else edit=0;}
{if (edit && $1 == "value1" ) $2="notbla";}1
' file
答案3
另一种awk
解决方案
$ cat ip.txt
[ABC]
value1=bla
value2=bla
value3=bla
[XYZ]
value1=bla
value2=bla
value3=bla
如果行以[
指定一个标志开头,则该标志将根据块名称设置或清除。然后如果设置了标志,则进行替换
$ awk '/^\[/{f=/\[ABC\]/} f{sub("value1=bla","value1=nobla")} 1' ip.txt
[ABC]
value1=nobla
value2=bla
value3=bla
[XYZ]
value1=bla
value2=bla
value3=bla
中的类似解决方案perl
,更改了演示的替代
$ perl -pe '$f=/\[ABC\]/ if /^\[/; s/value2=bla/value2=nobla/ if $f;' ip.txt
[ABC]
value1=bla
value2=nobla
value3=bla
[XYZ]
value1=bla
value2=bla
value3=bla
=
如果无论是否具体匹配到 ,都必须更改 右侧的所有内容bla
,请使用
awk '/^\[/{f=/\[ABC\]/} f{sub(/value1=.*/,"value1=nobla")} 1' ip.txt
perl -pe '$f=/\[ABC\]/ if /^\[/; s/value2=.*/value2=nobla/ if $f;' ip.txt