Unix 仅替换第一个匹配行,同时保留前导空格
我有一个文件,上面有这样一句话:Unix 仅替换第一个匹配行,同时保留前导空格,unix,sed,Unix,Sed,我有一个文件,上面有这样一句话: "cutoffTime": "20151024000000" 我想使用sed或grep查找以截止时间开始的行, 然后用另一个字符串替换整行,例如: "startTime" : "20151028000000" 编者按: 在问题和一些答案首次发布后,出现了两项额外要求,标题现在反映了这些要求: 在要替换的行的开头保留前导空格(或至少保留制表符) 仅替换第一个匹配行 使用sed sed 's/^"cutoffTime":.*/"startTime" : "2
"cutoffTime": "20151024000000"
我想使用sed或grep查找以截止时间开始的行
,
然后用另一个字符串替换整行,例如:
"startTime" : "20151028000000"
编者按: 在问题和一些答案首次发布后,出现了两项额外要求,标题现在反映了这些要求:
- 在要替换的行的开头保留前导空格(或至少保留制表符)
- 仅替换第一个匹配行
- 使用
sed
sed 's/^"cutoffTime":.*/"startTime" : "20151028000000"/' file
并检查结果。如果要修改原始文件
sed -i .bak 's/^"cutoffTime":.*/"startTime" : "20151028000000"/' file
命令的第一部分将第一个表达式(s
)替换为替换的^“cutoffTime”:.*
“startTime”:“20151028000000”
- 表达式匹配行的开头,后跟文本
后跟任何重复0次或多次的字符(“截止时间”:
)
sed
不支持-i选项时,您可以使用ed
ed -s request << EOF
,s/^"cutoffTime":.*/"startTime" : "20151028000000"/
w
q
EOF
如果要保留前导字符,请更改子条件行:
ed -s request << EOF
/cutoffTime
s/"cutoffTime.*/"startTime" : "20151028000000"/
w
q
EOF
ed-s请求根据OPs更新的查询使用这样的方法来查找和替换第一个外观,如下所示
sed '0,/^"cutoffTime":.*/{s/^"cutoffTime":.*/"startTime" : "20151028000000"/}' file
这将改变上述第一个出现的模式
要在源文件中进行替换,请使用-i
sed -i '0,/^"cutoffTime":.*/{s/^"cutoffTime":.*/"startTime" : "20151028000000"/}' file
说明:
sed '0,/<pattern>/{s/<pattern>/<replacement>/}' file
$ sed '0,/^"cutoffTime":.*/{s/^"cutoffTime":.*/"startTime" : "20151028000
000"/}' file1
"startTime" : "20151028000000"
"cutoffTime": "20151024000000"
"cutoffTime": "20151024000000"
要在行首保留前导空格,请执行以下操作:
sed 's/^\([[:blank:]]*\)"cutoffTime":.*$/\1"startTime" : "20151028000000"/' file
^\([[:blank:][]*\)
捕获行首的任何空格和制表符组合(如果存在),并将其前置到替换行(通过\1
,即对正则表达式中第一个(也是唯一的)捕获组的引用,实际上保留了原始行的前导空格
也只替换第一个匹配项:解决方案的复杂性取决于使用的sed
实现:
请注意,在以下两种解决方案中,/
(s//
)的形式-即省略正则表达式-意味着最近应用的正则表达式被隐式重用。
- GNU
sed
:
sed'0,/^\([[:blank:][]*\)“截止时间”:.*$/s/\1“开始时间”:“20151028000000”/”文件
0,/…/
是一个GNUsed
扩展,它允许正则表达式终止范围,即使它与第一行匹配(使用1
也不行,因为它总是从第一行开始范围,然后只在后续行上开始查找正则表达式)。实际上,这将范围限制为从正则表达式的第一次出现到文件的开头,无论它出现在何处,并且只替换该出现
- POSIX仅具有
sed
功能,如BSDsed
(也用于OS X):
replacement='“开始时间”:“20151028000000”
sed-e'1 s/^\([[:blank:][]*\)“截止时间”:.*$/\1'“$replacement”'/;t'\
-e'1,//s//\1'$replacement'/'文件
由于0,/…/
功能不是POSIX的一部分,匹配可能位于第一行的情况必须单独处理,因此上述情况首先只在1
行上查找匹配和替换;1,//
然后有效地从第2行查找,直到随后的第一个匹配和替换。请注意如果执行了替换,则第一次替换后的t
调用将结束脚本周期,这意味着永远不会输入范围1,//
。净效果是,替换只在正则表达式的第一次出现时发生,无论第一次出现在何处。亲爱的Matteo,感谢您的回复。这种方法很有效l当我把截止时间作为行的开头时,如果前面有一些标签,它就不起作用了。你能帮我稍微修改一下吗,这意味着它将找到截止时间的第一个外观,并用“开始时间”替换找到的截止时间位置的整句话:“20151028000000”。非常感谢。亲爱的沃尔特,谢谢你的回复。当我把截止时间作为行的开始时,这种方法很有效,如果我前面有一些标签,它就不起作用了。你能帮我更改一下吗?这意味着它将找到截止时间的第一个外观,并从找到截止时间的位置替换整个句子,带有“startTime”:“20151028000000”。非常感谢。然后您应该编辑您的问题并将所有要求放在那里。0,/…/
技术仅适用于处理第一个匹配项,但值得注意的是,此功能特定于GNUsed
;此外,您还可以使用s/
(emtpy regex在s
调用中),而不是从地址复制regex。
sed 's/^\([[:blank:]]*\)"cutoffTime":.*$/\1"startTime" : "20151028000000"/' file