我有这个文件:
"Max": 10,
"Enable": true,
"Min": 2,
"Enable": true,
"Retries": 5,
我想通过删除“启用”之后的所有内容来更改第二次出现的启用值:并输入我需要的值。 即使我用相同的字符串替换,我也不在乎“启用”只是替换现在的值。
我使用了这个命令:
sed -re 's/("Enable":)[^:]/\1 false,/2' file > newfile
但结果我得到了:
"Max": 10,
"Enable": true,
"Min": 2,
"Enable": false,true,
"Retries": 5,
如果可能,我需要使用sed命令。
谢谢大家!
答案 0 :(得分:2)
我知道你说你想要sed但sed是单行上的简单替换,这不是,所以你应该使用awk:
$ awk '/Enable/ && (++c==2) {$2="false,"} 1' file
"Max": 10,
"Enable": true,
"Min": 2,
"Enable": false,
"Retries": 5,
答案 1 :(得分:2)
这在sed中比在awk中更为迂回,但没关系。你所拥有的想法并不错,但是你遇到了sed以基于行的方式工作的问题:sed在模式空间中读取一行,在其上运行代码,然后读取下一行。除非进行特殊处理,否则您的代码一次只能看到一行,因此它不会看到第二次出现"Enable":
是第二次出现。
如果文件足够小以便完全保存在RAM中,那么简单的方法就是在处理之前将文件完全读入RAM:
sed ':a $! { N; ba }; s/\("Enable":\)[^\n]*/\1 false,/2' filename
那是:
:a # jump label for looping
$! { # Unless the end of input was reached
N # fetch the next line, append it
ba # go to :a
} # this reads the whole file into the
# pattern space. Then:
s/\("Enable":\)[^\n]*/\1 false,/2 # replace second occurrence of a matching
# value.
如果您正在使用Mac OS X或BSD:那些带有BSD sed的,这需要一些......啊...说服使用跳转指令。我相信它应该接受
sed -e ':a' -e '$! { N; ba' -e '}; s/\("Enable":\)[^\n]*/\1 false,/2' filename
可替换地,
sed '1h; 1!H; $!d; x; s/\("Enable":\)[^\n]*/\1 false,/2' filename
几乎完全相同,除了它在保持缓冲区而不是模式空间中汇编文件。
如果文件非常大,您可以使用
sed '1 { x; s/^/../; x; }; /"Enable":/ { x; /^.$/ { x; s/:.*/: false,/; x; }; s/.//; x; }' filename
其工作原理如下:
1 { # in the first line
x # set a counter in the hold buffer
s/^/../ # two dots here to replace the second occurrence.
x # (use n dots to replace the nth)
}
/"Enable":/ { # in a matching line:
x
/^.$/ { # check the counter. If it is one,
x
s/:.*/: false,/ # replace value
x
}
s/.// # decrease counter
x
}
x
交换保持缓冲区和模式空间,以便保持缓冲区的内容位于模式空间中并可以使用。他们中的很多人都认为合适的东西在合适的时间处于模式空间。
答案 2 :(得分:0)
<强>(更新)强> 本答案中提出的解决方案是将完整的文档读入内存......
使用Perl:在两个&#34;启用&#34;后,将.*
替换为false
:
perl -p0E 's!"Enable" (.|\n)*? "Enable": \K .* ! false!x'
在(gnu)Sed中,使用-z
(由NULL char分隔的寄存器)文件将成为
一个寄存器。在这种情况下,可以使用解决方案(类似于OP暂定):
sed -zr 's!"Enable":[^\n]*!"Enable": false!2'
or
sed -zr 's!("Enable":)[^\n]*!\1 false!2'
使用Perl策略在sed中无效,因为我们没有非贪婪的正则表达式运算符(如.*?
)。所以
sed -zr 's!("Enable"(.|\n)*?"Enable":)[^\n]*!\1 false!' ### WRONG
错了:只要我们有2次出现&#34;启用&#34;
就行了