我有一些看起来像这样的文本:
(something1)something2
但是 something1 和 something2 也可能在其中包含一些括号,例如
(some(thing)1)something(2)
我想提取something1
(包括内部括号,如果有的话)到一个变量。因为我可以指望文本总是以左括号开头,所以我希望我可以做一些事情,将第一个括号与正确的右括号匹配,并提取中间。
到目前为止,我尝试过的所有内容都有可能匹配错误的结尾括号。
我有一些看起来像这样的文本:
(something1)something2
但是 something1 和 something2 也可能在其中包含一些括号,例如
(some(thing)1)something(2)
我想提取something1
(包括内部括号,如果有的话)到一个变量。因为我可以指望文本总是以左括号开头,所以我希望我可以做一些事情,将第一个括号与正确的右括号匹配,并提取中间。
到目前为止,我尝试过的所有内容都有可能匹配错误的结尾括号。
如果您有 perl,则:
perl -MText::Balanced -nlE 'say [Text::Balanced::extract_bracketed( $_, "()" )]->[0]' <<EOF
(something1)something2
(some(thing)1)something(2)
(some(t()()hing)()1)()something(2)
EOF
将打印
(something1)
(some(thing)1)
(some(t()()hing)()1)
你可以用 perl 做到这一点:
echo "(some(thing)1)something(2)" | perl -ne '$_ =~ /(\((?:\(.*\)|[^(])*\))|\w+/s; print $1;'
由于这显然是正则表达式不可能实现的,所以我采用了 1 个 1 的字符:
first=""
count=0
while test -n "$string"
do
char=${string:0:1} # Get the first character
if [[ "$char" == ")" ]]
then
count=$(( $count - 1 ))
fi
if [[ $count > 0 ]]
then
first="$first$char"
fi
if [[ "$char" == "(" ]]
then
count=$(( $count + 1 ))
fi
string=${string:1} # Trim the first character
if [[ $count == 0 ]]
then
second="$string"
string=""
fi
done
awk
可以做到:
#!/bin/awk -f
{
for (i=1; i<=length; ++i) {
if (numLeft == 0 && substr($0, i, 1) == "(") {
leftPos = i
numLeft = 1
} else if (substr($0, i, 1) == "(") {
++numLeft
} else if (substr($0, i, 1) == ")") {
++numRight
}
if (numLeft && numLeft == numRight) {
print substr($0, leftPos, i-leftPos+1)
next
}
}
}
输入:
(something1)something2
(some(thing)1)something(2)
输出:
(something1)
(some(thing)1)