torr para corresponder ao padrão entre as chaves correspondentes

2

De um padrão como

[string 1]{string 2}

Eu quero extrair string 2 , a cadeia entre o par último de chaves correspondência - que é excluir [string 1] e abrir { e fechar } . Minha tentativa abaixo será interrompida quando houver mais [ , ] pares em string 1 ou string 2 .

Saída desejada:

A saída desejada do script abaixo começa com foo e termina com 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'

Suposições:

  • O parâmetro para RemoveInitialSquareBraces sempre começa com [ e termina com } .
  • A abertura [ para string 1 terá uma ] correspondente no ponto em que a abertura { começa por string 2 .

Plataforma:

  • MacOS 10.9.5

Script

#!/bin/bash

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

    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
    
por Peter Grill 11.01.2016 / 10:07

2 respostas

2

Com relação aos exemplos de entrada acima, o script pode ser:

sed s/[^\"\']*[^0-9]\]{\(.*\)}// <<\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

produz

"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"

Outra coisa é a sua função, que pode ser simplificada:

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

assim aceitará muitos argumentos.

Atualizar : para casos mais gerais, você pode realizar a tarefa em duas etapas:

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

Adição : você pode usar perl- grep (GNU grep com extensão de perl):

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

ou sed com o mesmo regexp:

sed 's/\[\([^][]*\(\[\w\+\][^][]*\)*\)*\]{\(.*\)}//'
    
por 11.01.2016 / 10:53
1

Isso funciona para sua opinião:

sed -Ee's/.*(\{[^}]*(\{[^{}]*\}[^{]*)*\})//'
{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}'

Ele apenas remove tudo antes da última ocorrência em uma linha de um par de curlies correspondente que pode conter totalmente qualquer número de outros pares de correspondências.

    
por 11.01.2016 / 15:27