Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 仅替换第一个匹配行,同时保留前导空格_Unix_Sed - Fatal编程技术网

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,/…/
      是一个GNU
      sed
      扩展,它允许正则表达式终止范围,即使它与第一行匹配(使用
      1
      也不行,因为它总是从第一行开始范围,然后只在后续行上开始查找正则表达式)。实际上,这将范围限制为从正则表达式的第一次出现到文件的开头,无论它出现在何处,并且只替换该出现

      • POSIX仅具有
        sed
        功能,如BSD
        sed
        (也用于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,/…/
      技术仅适用于处理第一个匹配项,但值得注意的是,此功能特定于GNU
      sed
      ;此外,您还可以使用
      s/
      (emtpy regex在
      s
      调用中),而不是从地址复制regex。
      sed 's/^\([[:blank:]]*\)"cutoffTime":.*$/\1"startTime" : "20151028000000"/' file