Bash:需要在文本中的匹配大括号(圆括号)中查找文本

时间:2013-05-31 20:45:46

标签: regex bash pattern-matching

我有一些看起来像这样的文字:

(something1)something2

然而,something1和something2也可能在其中包含一些括号,例如

(some(thing)1)something(2)

我想将something1(包括内部括号,如果有的话)提取到变量中。因为我可以指望总是以开括号开头的文本,我希望我可以做一些事情,我将第一个括号与正确的右括号匹配,并提取中间。

到目前为止我尝试的所有内容都有可能匹配错误的结束括号。

4 个答案:

答案 0 :(得分:3)

如果你有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)

答案 1 :(得分:2)

你可以使用perl:

echo "(some(thing)1)something(2)" | perl -ne '$_ =~ /(\((?:\(.*\)|[^(])*\))|\w+/s; print $1;'

答案 2 :(得分: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

答案 3 :(得分:1)

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)