是否可以使用 shell 命令查找和替换包含单个字符的行?
Is it possible to find and replace line containing single character using shell commands?
是否可以使用 sed
或 awk
或任何其他 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/(\(.*\))/{}/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
}
+ ...
而我知道如何避免它,例如我可以合并行使其成为单行,然后我可以使用命令将最外面的 (...)
替换为 {...}
。然而,这些还有一些其他的后果,并不是这个问题所特有的。
我的主要问题不是为这些示例解决问题,而是了解是否有可能检测和替换文件中仅包含一个字符 )
的行,而文件中可能有许多其他 )
的出现,其中一些字符将完好无损。
您可以使用以下任一方式:
sed -e 's/(\(.*\))/{}/g'
这将始终用 { }
替换最外层的括号,如下所示:
$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\(.*\))/{}/g'
foo { 1 + ((f)) }
或类似这样的东西,它将始终替换 innermost 括号:
sed -e 's/(\([^()]*\))/{}/'
例如,
$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\([^()]*\))/{}/g'
foo ( 1 + ({f}) )
或者,您在问题中指定的确切行为:
$ echo 'foo ( 1 + ((f)) )' | sed -e 's/\((.*\))/}/g'
foo ( 1 + ((f)) }
您实际上无法用单个正则表达式进行正确的括号替换,它必须是某种迭代过程。这是因为你不能用正则表达式来计算。
这可能对你有用 (GNU sed):
sed 's/)/&/2;t;s//}/' file
将第二次出现的 )
替换为自身并退出,否则将其替换为 }
。
使用任何 POSIX sed:
$ sed 's/^\([[:space:]]*\))\([[:space:]]*\)$/}/' file
exp = ... +
( x
+ 2*(y)
+ z
}
+ ...
如果你想对正在发生的事情有更多的感觉,你可以使用awk
:
awk '(NF==1)&&(==")") { sub(/\)/,"}") } 1'
内容为,_如果该行包含一个字段并且该字段是字符 ")",则用您想要的内容替换该行中的括号。
是否可以使用 sed
或 awk
或任何其他 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/(\(.*\))/{}/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
}
+ ...
而我知道如何避免它,例如我可以合并行使其成为单行,然后我可以使用命令将最外面的 (...)
替换为 {...}
。然而,这些还有一些其他的后果,并不是这个问题所特有的。
我的主要问题不是为这些示例解决问题,而是了解是否有可能检测和替换文件中仅包含一个字符 )
的行,而文件中可能有许多其他 )
的出现,其中一些字符将完好无损。
您可以使用以下任一方式:
sed -e 's/(\(.*\))/{}/g'
这将始终用 { }
替换最外层的括号,如下所示:
$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\(.*\))/{}/g'
foo { 1 + ((f)) }
或类似这样的东西,它将始终替换 innermost 括号:
sed -e 's/(\([^()]*\))/{}/'
例如,
$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\([^()]*\))/{}/g'
foo ( 1 + ({f}) )
或者,您在问题中指定的确切行为:
$ echo 'foo ( 1 + ((f)) )' | sed -e 's/\((.*\))/}/g'
foo ( 1 + ((f)) }
您实际上无法用单个正则表达式进行正确的括号替换,它必须是某种迭代过程。这是因为你不能用正则表达式来计算。
这可能对你有用 (GNU sed):
sed 's/)/&/2;t;s//}/' file
将第二次出现的 )
替换为自身并退出,否则将其替换为 }
。
使用任何 POSIX sed:
$ sed 's/^\([[:space:]]*\))\([[:space:]]*\)$/}/' file
exp = ... +
( x
+ 2*(y)
+ z
}
+ ...
如果你想对正在发生的事情有更多的感觉,你可以使用awk
:
awk '(NF==1)&&(==")") { sub(/\)/,"}") } 1'
内容为,_如果该行包含一个字段并且该字段是字符