仅替换第一个匹配行,同时保留前导空格

Le *_*ang 3 unix sed

我有一个文件,其中包含以下句子:

"cutoffTime": "20151024000000"
Run Code Online (Sandbox Code Playgroud)

我想使用 sed 或 grep 查找以 开头的行cutoffTime,然后用另一个字符串替换整行,例如:

"startTime" : "20151028000000"
Run Code Online (Sandbox Code Playgroud)

编者注:

在问题和几个答案首次发布,出现了两个额外的要求,现在的标题反映了这些要求:

  • 保留要替换的行开头的前导空格(或至少是制表符)。

  • 仅替换第一个匹配行。

mkl*_*nt0 5

要保留行开头的前导空格:

sed 's/^\([[:blank:]]*\)"cutoffTime":.*$/\1"startTime" : "20151028000000"/' file
Run Code Online (Sandbox Code Playgroud)
  • ^\([[:blank:]]*\)捕获行开头处的空格和制表符的任意组合(如果存在)并将其添加到替换行(通过\1,对正则表达式中的第一个(也是唯一的)捕获组的引用,实际上保留了前导空格原线。

仅替换一个匹配项:解决方案的复杂性取决于sed所使用的实现:

//请注意,在下面的两种解决方案中, ( )形式s//(即省略正则表达式)意味着隐式重用最近应用的正则表达式。

  • GNU sed
sed 's/^\([[:blank:]]*\)"cutoffTime":.*$/\1"startTime" : "20151028000000"/' file
Run Code Online (Sandbox Code Playgroud)

0,/.../是一个GNU sed扩展,允许正则表达式终止范围,即使它匹配第一(使用1它不会这样做,因为它总是从第一行开始范围,然后只开始在后续的正则表达式中查找)行)。实际上,这将范围限制为从文件开头到正则表达式第一次出现(无论它出现在何处),并且仅替换该出现的位置。

  • 仅 POSIX 功能,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,//