【问题标题】:Modify eachline characters between two patterns修改两个模式之间的每一行字符
【发布时间】:2018-09-01 18:58:03
【问题描述】:

我需要修改每行两个模式之间的某些字符。

示例::(文件内容保存为 myfile.txt)

abc, def, 1, {,jsdfsd,kfgdsf,lgfgd}, 2, pqr, stu
abc, def, 1, {,jsdfsqwe,k,fdfsfl}, 2, pqr, stu
abc, def, 1, {,asdasdj,kgfdgdf,ldsfsdf}, 2, pqr, stu
abc, def, 1, {,jsds,kfdsf,fdsl}, 2, pqr, stu

我想编辑和保存 myfile.txt,如下所述

abc, def, 1, {jsdfsd kfgdsf lgfgd}, 2, pqr, stu
abc, def, 1, {jsdfsqwe k fdfsfl}, 2, pqr, stu
abc, def, 1, {asdasdj kgfdgdf ldsfsdf}, 2, pqr, stu
abc, def, 1, {jsds kfdsf fdsl}, 2, pqr, stu

我使用以下命令来编辑和保存 myfile.txt

sed '/1,/,/,2/{/1,/n;/,2/!{s/,/ /g}}' myfile.txt

这个命令没有帮助我实现我的目标。请帮助解决此问题。

【问题讨论】:

  • /1,/,/,2/ 语法用于多行匹配,而不是同一行
  • 请解释您的更改应该发生的规则。对于给定的 ip/op,sed 's/,/ /6; s/,/ /5; s/,//4' 可以工作.. 但它适用于您的实际用例吗?

标签: shell file vim sed


【解决方案1】:

awk 在这种情况下会更合适:

awk 'BEGIN{ FS=OFS=", " }{ gsub(/,/, " ", $4); sub(/\{ /, "{", $4) }1' file

输出:

abc, def, 1, {jsdfsd kfgdsf lgfgd}, 2, pqr, stu
abc, def, 1, {jsdfsqwe k fdfsfl}, 2, pqr, stu
abc, def, 1, {asdasdj kgfdgdf ldsfsdf}, 2, pqr, stu
abc, def, 1, {jsds kfdsf fdsl}, 2, pqr, stu

【讨论】:

    【解决方案2】:

    您能否尝试关注awk,如果这对您有帮助,请告诉我。

    awk 'match($0,/{.*}/){val=substr($0,RSTART,RLENGTH);gsub(/,/," ",val);gsub(/{ /,"{",val);gsub(/} /,"}",val);print substr($0,1,RSTART-1) val substr($0,RSTART+RLENGTH+1);next} 1'  Input_file
    

    现在也添加非单线形式的解决方案。

    awk '
    match($0,/{.*}/){
      val=substr($0,RSTART,RLENGTH);
      gsub(/,/," ",val);
      gsub(/{ /,"{",val);
      gsub(/} /,"}",val);
      print substr($0,1,RSTART-1) val substr($0,RSTART+RLENGTH+1)
      next
    }
    1
    '   Input_file
    

    【讨论】:

      【解决方案3】:

      因为你也有标签vim,你可以在vim中通过:

      :%normal 0f{vi{:s/\%V,/ /g^M

      最后两个字符实际上是 Ctrl+V 后跟 Ctrl+M

      【讨论】:

      • 第一个逗号应该删除。看看下面我的 vim 解决方案。
      【解决方案4】:

      使用 vim:

      :%normal! 4f,xf,r f,r 
      
      : ........... command mode
      % ........... in the whole file
      normal! ..... normal mode
      4f, ......... jump inside { block
      x ........... delete the first comma
      f, .......... jump to the next comma
      r<Space> .... replace comma with space
      

      【讨论】:

      • 4f, 跳转到 { 块内,因为在 { 之前正好有 3 个逗号,而在里面有一个逗号。我建议实际上找到第一个{ 字符。也许这两种解决方案都以自己的方式工作,但如果你想解释它是如何工作的,jump inside { block 有点误导。 (另一种方法是什么都不解释:-P)
      【解决方案5】:

      在 vim 中也有前瞻和后瞻的可能性:

      %s/\v(\{.*)@<=,(.*})@=/ /g 
      

      匹配{} 之间的每个,,并用空格替换它们。

      如果是这种情况,应该删除直接在{之后的,,而不是用空格替换,可以先在稍微修改的版本中运行此行:

      %s/\v(\{)@<=,(.*})@=/ /g 
      

      【讨论】:

        【解决方案6】:

        一种选择是在您的:substitute 命令中使用子替换表达式。

        :%s/{\zs[^}]*\ze}/\=substitute(submatch(0)[1:], ',', ' ', 'g')
        

        这匹配在你的花括号之间,然后用空格替换每个,,同时避免第一个逗号。

        如需更多帮助,请参阅:

        :h sub-replace-expression
        :h /\zs
        :h submatch()
        :h sublist
        :h substitute()
        

        【讨论】:

          【解决方案7】:

          还有一些 awk:

          awk 'NR>1{gsub(/,/," ",$1); $0=RS $0}1' FS=} OFS=} RS={ ORS= file
          

          awk '{gsub(/,/, " ", $2); $2="{" $2 "}"}1' FS='[{}]' OFS= file
          

          【讨论】:

            猜你喜欢
            • 2022-10-24
            • 1970-01-01
            • 1970-01-01
            • 2016-11-20
            • 1970-01-01
            • 2023-03-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多