我怎样才能只在括号内的行上进行操作?
例如,我想更改“.is”行并添加括号,但不更改带有未闭合括号的行。
所以这些都改变了
this_thing.is 24 -> (this_thing).is 24
that.is 50 -> (that).is 50
a[23].is == 10 -> a[23].is == 10
a.is true -> (this_thing).is 24
this_thing.is 24 -> (this_thing).is 24
但这些不是:
this_thing.is (24
((that).is 50
(a[23].is == 10
a.is ( true
(this_thing.is 24
理想情况下也(不)
a{.is true
this_thing{.is 24
并不是)
a[.is true
this_thing[.is 24
我有一个带有 /.is/ 的匹配器,但是如何匹配不匹配的括号?
答案1
就我个人而言,如果我的正则表达式接近这种复杂程度,我会将整个操作切换到 Perl。这一个处理任意数量的左大括号/圆括号/大括号:
$ perl -ne '@open=/[\[({]/g; @close=/[)\]}]/g;
if($#close == $#open){s/(.+?)\.is/($1).is/} print' file
或者,更紧凑:
$ perl -pne 's/(.+?)\.is/($1).is/ if $#{/[\[({]/g} == $#{/[)\]}]/g}' file
或者更完整的是,这个可以处理类似的情况[}
(但在类似的情况下仍然失败)(
):
$ perl -pne '@osqb=/\[/g; @csqb=/\]/g;
@ocb=/\{/g; @ccb=/\}/g;
@op=/\(/g; @cp=/\)/g;
if($#osqb == $#csqb && $#ocb==$#ccb && $#op == $#cp){
s/(.+?)\.is/($1).is/
}' file
当在您的示例上运行时,这将打印
(this_thing).is 24
(that).is 50
(a[23]).is == 10
(a).is true
(this_thing).is 24
this_thing.is (24
((that).is 50
(a[23].is == 10
a.is ( true
(this_thing.is 24
a{.is true
this_thing{.is 24
a[.is true
this_thing[.is 24
解释
perl -ne
:逐行处理输入文件 (-n
) 并运行 给出的脚本-e
。@open=/[\[({]/g;
:找到所有打开的字形并将结果保存在名为 的数组中@open
。@close=/[)\]}]/g;
: 如上所述,但用于关闭字形。if($#close == $#open)
:如果左字形的数量等于右字形的数量(换句话说,如果有挂括号等)...s/(.+?)\.is/($1).is/
.is
: ...然后替换以括号内的自身结尾的最短字符串。- 最后一个
print
在括号外,无论是否有替换都会被执行。
答案2
扩展 terdon 的答案,您可以使用 Perl 来真正解析嵌套的括号结构。这是一个应该执行此操作的正则表达式:
$balanced_parens_grammar = qr/
(?(DEFINE) # Define a grammar
(?<BALANCED_PARENS>
\( # Opening paren
(?: # Group without capturing
(?&BALANCED_PARENS) # Nested balanced parens
|(?&BALANCED_BRACKETS) # Nested balanced brackets
|(?&BALANCED_CURLIES) # Nested balanced curlies
|[^)]* # Any non-closing paren
) # End alternation
\) # Closing paren
)
(?<BALANCED_BRACKETS>
\[ # Opening bracket
(?: # Group without capturing
(?&BALANCED_PARENS) # Nested balanced parens
|(?&BALANCED_BRACKETS) # Nested balanced brackets
|(?&BALANCED_CURLIES) # Nested balanced curlies
|[^\]]* # Any non-closing bracket
) # End alternation
\] # Closing bracket
)
(?<BALANCED_CURLIES>
{ # Opening curly
(?: # Group without capturing
(?&BALANCED_PARENS) # Nested balanced parens
|(?&BALANCED_BRACKETS) # Nested balanced brackets
|(?&BALANCED_CURLIES) # Nested balanced curlies
|[^}]* # Any non-closing curly
) # End alternation
} # Closing curly
)
)
(?<BALANCED_ANY>
(?:
(?&BALANCED_PARENS)
|(?&BALANCED_BRACKETS)
|(?&BALANCED_CURLIES)
)
)
/x;
像这样使用它:
if( $line =~ m/
^
[^()\[\]{}]* # Any non-parenthetical punctuation
(?&BALANCED_ANY)? # Any balanced paren-types
[^()\[\]{}]*
$
$balanced_parens_grammar/x){
# Do your magic here
}
免责声明
代码完全未经测试。可能包含错误。
答案3
Sed 使用正则表达式,正则表达式对此不够强大。使用 gawk 或其他可以执行此操作的工具。
有一个语法分类表明了这一点:常规语法、上下文无关语法等。常规语言无法完成括号匹配。所以你不能可靠地做到这一点。