我想更改文本文件中特定组的PATH
和。LOC_NAME
例如:
[a]
PATH=/tmp
SUR=Y
LOC_NAME=USA
[b]
PATH=/tmp
SUR=N
LOC_NAME=UK
因此,如果要进行搜索,[b]
我只想更改其后的第一个匹配项(在下一个之后而不是在之后[*]
):
sed -i '/PATH/c\PATH=\/u01'
sed -i '/LOC_NAME/c\LOC_NAME=RUS'
答案1
你们非常接近!
您可以添加一个地址范围对于应该改变的部分。如果您想保持块外从以[b]
开始的行到下一行的所有内容不变[
,请在两个表达式之间选择一个带有逗号的地址范围(现在您只有要更改的块),用 an 反转它!
(现在您得到了其他一切)并使用命令b
分支到脚本的末尾。因此,后面的每个命令只会影响范围内的行:
sed -i '/^\[b\]$/,/^\[/!b
/PATH/c\PATH=\/u01
/LOC_NAME/c\LOC_NAME=RUS'
当然,您可以使用块{commands;...;}
来进行非反转匹配,而不是反转和分支,但我认为这可读性较差。
如果你想使用变量中的单词作为标识符,你可以这样做:
ID=foo
sed -i '/^\['$ID'\]$/,/^\[/!b
/PATH/c\PATH=\/u01
/LOC_NAME/c\LOC_NAME=RUS'
答案2
awk
使用Perl可能更容易:
$ cat input
[a]
PATH=/tmp
[b]
PATH=/tmp
OTHERPATH=/somedir
[c]
PATH=/tmp
$ gr="[b]"
$ repl=/u01
$ awk -vgr="$gr" -vrepl="$repl" '/^\[.*\]$/ { group=$0 } group == gr && /^PATH=/ { $0 = "PATH=" repl } 1' input
[a]
PATH=/tmp
[b]
PATH=/u01
OTHERPATH=/somedir
[c]
PATH=/tmp
$ gr=b
$ repl=/u01
$ gr=$gr repl=$repl perl -pe '$group = $1 if /^\[(.*)\]$/; s,^PATH=.*,PATH=$ENV{repl}, if $group eq $ENV{gr}' < input
[same output]
这个想法是找到具有 的行[something]
,记下那里的名称,然后以此为条件进行替换。 (请注意,awk 版本采用带括号的组名,而 Perl 版本则不带括号。后者更漂亮,但在 awk 中不像 Perl 那样简单。Perl 版本通过环境获取变量,因此您需要到export
gr
和repl
,或将它们分配在同一命令行上。)
我修改了它,仅当密钥恰好是 时才进行替换PATH
,但这些仍然会更改PATH
同一[b]
标题下的所有 s (不仅仅是第一个),但我不确定是否可以有多个。