我有一个文件,其中包含以下句子:
"cutoffTime": "20151024000000"
Run Code Online (Sandbox Code Playgroud)
我想使用 sed 或 grep 查找以 开头的行cutoffTime,然后用另一个字符串替换整行,例如:
"startTime" : "20151028000000"
Run Code Online (Sandbox Code Playgroud)
编者注:
在问题和几个答案首次发布后,出现了两个额外的要求,现在的标题反映了这些要求:
保留要替换的行开头的前导空格(或至少是制表符)。
仅替换第一个匹配行。
要保留行开头的前导空格:
sed 's/^\([[:blank:]]*\)"cutoffTime":.*$/\1"startTime" : "20151028000000"/' file
Run Code Online (Sandbox Code Playgroud)
^\([[:blank:]]*\)捕获行开头处的空格和制表符的任意组合(如果存在)并将其添加到替换行(通过\1,对正则表达式中的第一个(也是唯一的)捕获组的引用,实际上保留了前导空格原线。仅替换第一个匹配项:解决方案的复杂性取决于sed所使用的实现:
//请注意,在下面的两种解决方案中, ( )形式s//(即省略正则表达式)意味着隐式重用最近应用的正则表达式。
sed:sed 's/^\([[:blank:]]*\)"cutoffTime":.*$/\1"startTime" : "20151028000000"/' file
Run Code Online (Sandbox Code Playgroud)
0,/.../是一个GNU sed扩展,允许正则表达式终止范围,即使它匹配第一行(使用1它不会这样做,因为它总是从第一行开始范围,然后只开始在后续的正则表达式中查找)行)。实际上,这将范围限制为从文件开头到正则表达式第一次出现(无论它出现在何处),并且仅替换该出现的位置。
sed例如BSD sed(也在 OS X 上使用):sed '0,/^\([[:blank:]]*\)"cutoffTime":.*$/ s//\1"startTime" : "20151028000000"/' file
Run Code Online (Sandbox Code Playgroud)
由于该功能不是 POSIX 的一部分,因此必须单独处理匹配可能位于第一0,/.../行的情况,因此上面的第一个仅在行中查找匹配并进行替换;然后有效地从第 2 行开始查找,直到随后的第一场比赛并替换。请注意,如果执行了替换,则第一次替换后的调用会结束脚本循环,这意味着永远不会输入该范围。最终效果是,仅在正则表达式第一次出现时进行替换,无论第一次出现在何处。11,//t1,//