Extraindo uma string, de acordo com um padrão, em um script bash

16

No bash, suponha que eu tenha uma string strname :

strname="ph7go04325r"

Eu gostaria de extrair os caracteres entre o caractere primeiro "3" e o caractere último "r" em strname , salvando o resultado em uma string% código%. No exemplo acima, o strresult resultante seria:

strresult="25"

O primeiro caractere strresult é não necessariamente na posição 8 da string em "3" ; da mesma forma, o último strname não é necessariamente na posição da string 11. Assim, ambas as seguintes strings "r" devem render strname :

strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"

Além disso, strresult="25" deve render strname=ph12go04330raa" .

Eu sou novo no bash scripting, e não sei onde começar a fazer correspondência de padrões de string como essa. Você tem alguma sugestão?

    
por Andrew 04.02.2013 / 20:56

2 respostas

24

Você pode usar um regex no bash (3.0 ou superior) para fazer isso:

if [[ $strname =~ 3(.+)r ]]; then
    strresult=${BASH_REMATCH[1]}
else
    echo "unable to parse string $strname"
fi

No bash, os grupos de captura de uma expressão regular são colocados na matriz especial BASH_REMATCH . O elemento 0 contém a correspondência inteira e 1 contém a correspondência do primeiro grupo de captura.

    
por 04.02.2013 / 21:03
10

Na sintaxe sh padrão (assim funcionaria com qualquer versão de bash ou qualquer outro shell compatível com POSIX), você faria:

case $strname in
  (*3*r*) 
    strresult=${strname#*3}
    strresult=${strresult%r*};;
  (*)
    printf >&2 '%s\n' "Unable to parse string $strname"
esac

Veja também a antiga solução expr , que funcionará em Unices de 35 anos:

expr "x$strname" : 'x[^3]*3\(.*\)r'

O antigo quirk com expr é que, se a correspondência falhar, você obterá um status de saída diferente de zero (bom), mas também obterá um status de saída diferente de zero se as sequências retornadas resolverem para 0 (como com strname=zz300rzz ).

    
por 04.02.2013 / 21:21