【问题标题】:Bash: need to find text within matching braces (parantheses) in textBash:需要在文本中匹配的大括号(括号)内查找文本
【发布时间】:2013-05-27 18:31:48
【问题描述】:

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

(something1)something2

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

(some(thing)1)something(2)

我想将something1(包括内部括号,如果有的话)提取到一个变量中。由于我可以依靠始终以左括号开头的文本,我希望我可以做一些事情,将第一个括号与正确的右括号匹配,并提取中间。

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

【问题讨论】:

  • 用正则表达式找到匹配的括号是不可能的,所以像一个字符一个字符地搜索字符串直到开括号和右括号的数量相等的方法可能是最好的方法
  • 谢谢,我发现你是对的。
  • @Angelo Perl 正则表达式(严格来说,不是真正的正则表达式,因为它们更强大)可以匹配括号,并受 grep 支持(GNU grep,在最少)。
  • 虽然 perl 可以用正则表达式做到这一点,但可以在 bash 中做到这一点。

标签: regex bash pattern-matching


【解决方案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

【讨论】:

    【解决方案2】:

    你可以用 perl 做到这一点:

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

    【讨论】:

      【解决方案3】:

      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)
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2019-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-19
          • 2017-01-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多