sed 匹配匹配花括号之间的模式

sed 匹配匹配花括号之间的模式

从这样的模式

[string 1]{string 2}

我想提取string 2之间的字符串最后的匹配大括号——即删除[string 1]以及打开{和关闭}。当or中存在额外的[,]对时,我下面的尝试就会失败。string 1string 2

期望的输出:

下面脚本的所需输出以 开头foo和结尾digit

foo bar 1
foo bar 2
foo[3]{xyz} bar 3
foo $sq[3]{xyz}$ bar 4
foo $sq[3]{xyz}$ bar 5
foo $sq[3]{xyz}$ bar 6
foo $sq[3]{xyz}$ bar 7
foo $sq[3]{xyz}$ bar 8'
foo $sq[abc]{xyz}$ bar 9'
foo $sq[abc]{xyz}$ bar 10'

假设:

  • 参数为RemoveInitialSquareBraces 总是以 a 开头[,以 a 结束}
  • 开幕[式为string 1 将要在的]开头处有一个匹配。{string 2

平台:

  • 苹果系统 10.9.5

脚本

#!/bin/bash

function RemoveInitialSquareBraces {
    #EXTRACTED_TEXT="$(\
    #      echo "$1" \
    #    | sed 's/^\[.*\]//'              \
    #    | sed 's/{//'                    \
    #    | sed 's/}$//'                   \
    #    )"
    EXTRACTED_TEXT="$(\
          echo "$1" \
        | sed 's/.*[^0-9]\]{\(.*\)}/\1/' \
        )"
        
    echo "${EXTRACTED_TEXT}"
}

RemoveInitialSquareBraces '[]{foo bar 1}'
RemoveInitialSquareBraces '[abc]{foo bar 2}'
RemoveInitialSquareBraces '[]{foo[3]{xyz} bar 3}'
RemoveInitialSquareBraces '[]{foo $sq[3]{xyz}$ bar 4}'
RemoveInitialSquareBraces '[goo{w}]{foo $sq[3]{xyz}$ bar 5}'
RemoveInitialSquareBraces '[goo[3]{w}]{foo $sq[3]{xyz}$ bar 6}'
RemoveInitialSquareBraces '[goo[3]{w} hoo[3]{5}]{foo $sq[3]{xyz}$ bar 7}'
RemoveInitialSquareBraces '[goo[3]{w} hoo[3]{5}]{foo $sq[3]{xyz}$ bar 8}'
RemoveInitialSquareBraces '[goo[3]{w} hoo[xyz]{5}]{foo $sq[abc]{xyz}$ bar 9}'
RemoveInitialSquareBraces '[goo[3]{w} hoo[xyz]{uvw}]{foo $sq[abc]{xyz}$ bar 10}'

exit 0

答案1

对于上面的输入示例,脚本可以是:

sed s/[^\"\']*[^0-9]\]{\(.*\)}/\1/ <<\END
"[]{foo bar 1}"
"[abc]{foo bar 2}"
"[]{foo[3]{xyz} bar 3}"
"[]{foo $sq[3]{xyz}$ bar 4}"
"[goo{w}]{foo $sq[3]{xyz}$ bar 5}"
"[goo[3]{w}]{foo $sq[3]{xyz}$ bar 6}"
"[goo[3]{w} hoo[3]{5}]{foo $sq[3]{xyz}$ bar 7}"
END

产生

"foo bar 1"
"foo bar 2"
"foo[3]{xyz} bar 3"
"foo $sq[3]{xyz}$ bar 4"
"foo $sq[3]{xyz}$ bar 5"
"foo $sq[3]{xyz}$ bar 6"
"foo $sq[3]{xyz}$ bar 7"

另一件事是你的功能可以简化:

function RemoveInitialSquareBraces {
    printf '%s\n' "$@" |
    sed ...
}

因此它将接受许多参数。

更新:对于更一般的情况,您可以分两步完成任务:

sed -e "
s/\[.*\[.*\][^[]*\]/[]/  #remove square brackets inside square brackets
s/\[[^]]*\]{\(.*\)\}/\1/ #lazy strip square brackets and curle brackets
"

添加:你可以使用perl-grep(带 perl 扩展的 GNU grep):

grep -Po '\[([^][]*\[\w+\][^][]*)*\]{\K.*(?=})'

或 sed 具有相同的正则表达式:

sed 's/\[\([^][]*\(\[\w\+\][^][]*\)*\)*\]{\(.*\)}/\3/'

答案2

这适用于您的输入:

sed -Ee's/.*(\{[^}]*(\{[^{}]*\}[^{]*)*\})/\1/'

{foo bar 1}'
{foo bar 2}'
{foo[3]{xyz} bar 3}'
{foo $sq[3]{xyz}$ bar 4}'
{foo $sq[3]{xyz}$ bar 5}'
{foo $sq[3]{xyz}$ bar 6}'
{foo $sq[3]{xyz}$ bar 7}'
{foo $sq[3]{xyz}$ bar 8}'
{foo $sq[abc]{xyz}$ bar 9}'
{foo $sq[abc]{xyz}$ bar 10}'

它只是删除匹配的卷曲对行中最后一次出现之前的所有内容,该行可能完全包含任意数量的其他匹配的卷曲对。

相关内容