是否可以使用shell命令查找和替换包含单个字符的行?

时间:2018-11-25 15:13:57

标签: bash awk sed replace str-replace

是否可以使用sedawk或任何其他Shell命令来识别具有单个字符的行,例如),然后换成其他东西吗? 可能有很多行包含),但它仅替换了包含单个字符)的行。 示例:

exp =  ... +
     (    x  
        + 2*(y) 
        + z
      )
       + ...

我想要得到的是以下

exp =  ... +
     (    x 
        + 2*(y) 
        + z
      }
       + ...

如果我使用普通的sed命令替换),它将用)替换所有匹配项。

sed -i -e 's/)/\}/g' file

会给出

exp =  ... +
     (    x
        + 2*(y} 
        + z
      }
       + ...

有没有出路?

编辑:带嵌套括号的示例,其中一行包含内部嵌套括号,该解决方案不起作用(对于此示例):

sed -e 's/(\(.*\))/{\1}/g'

      ...
   + LNb * (
      + ( - 224/27 + ( - 8/3)*Lqf^2 + (80/9)*Lqf)*CF*NF
      + (1616/27 - 56*[Zeta[3]] + ( - 536/9 + 16*[Zeta[2]])*Lqf + (44/3)*
     Lqf^2)*CF*CA
      + ((32 - 128*[Zeta[2]])*Lqf)*CF^2
      )
     + ...

给出

      ...
   + LNb * (
      + { - 224/27 + ( - 8/3)*Lqf^2 + (80/9)*Lqf}*CF*NF
      + {1616/27 - 56*[Zeta[3]] + ( - 536/9 + 16*[Zeta[2]])*Lqf + (44/3}*
     Lqf^2)*CF*CA
      + {(32 - 128*[Zeta[2]])*Lqf}*CF^2
      )
     + ...

不同
      ...
   + LNb * {
      + ( - 224/27 + ( - 8/3)*Lqf^2 + (80/9)*Lqf)*CF*NF
      + (1616/27 - 56*[Zeta[3]] + ( - 536/9 + 16*[Zeta[2]])*Lqf + (44/3)*
     Lqf^2)*CF*CA
      + ((32 - 128*[Zeta[2]])*Lqf)*CF^2
      }
     + ...

例如,我知道如何避免它,例如,我可以合并行,以使其变为单行,然后可以使用命令将最外面的(...)替换为{...}。但是,这些还有一些其他后果,而不仅仅是该问题。

我的主要查询不是针对这些示例进行计算,而是了解是否有可能检测和替换文件中仅包含一个字符)的行,而没有其他任何文件(文件中可能还有许多其他字符)出现)且某些字符完整无缺。

4 个答案:

答案 0 :(得分:1)

您可以使用以下任一方式:

sed -e 's/(\(.*\))/{\1}/g'

总是将最外面的括号替换为{ },就像这样:

$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\(.*\))/{\1}/g'
foo { 1 + ((f)) }

或者类似这样的东西,它们将始终替换最内层括号:

sed -e 's/(\([^()]*\))/{\1}/'

例如,

$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\([^()]*\))/{\1}/g'
foo ( 1 + ({f}) )

或者,您在问题中指定的确切行为:

$ echo 'foo ( 1 + ((f)) )' | sed -e 's/\((.*\))/\1}/g'
foo ( 1 + ((f)) }

实际上不能使用单个正则表达式来进行正确的括号替换,这必须是某种迭代过程。这是因为您不能使用正则表达式。

答案 1 :(得分:1)

使用任何POSIX sed:

$ sed 's/^\([[:space:]]*\))\([[:space:]]*\)$/\1}\2/' file
exp =  ... +
     (    x
        + 2*(y)
        + z
      }
       + ...

答案 2 :(得分:1)

如果您想对发生的事情有更多了解,可以使用awk

awk '(NF==1)&&($1==")") { sub(/\)/,"}") } 1'

读到的是,_if如果该行包含一个字段,并且该字段是字符“)”,则在该行中用您想要的括号代替。

答案 3 :(得分:0)

这可能对您有用(GNU sed):

sed 's/)/&/2;t;s//}/' file

自行替换第二次出现的)并纾困,否则将其替换为}