Extraindo uma sequência, de acordo com um padrão, em um script bash

17

No bash, suponha que eu tenha uma string strname:

strname="ph7go04325r"

Gostaria de extrair os caracteres entre o primeiro "3" e o último "r" caractere strname, salvando o resultado em uma string strresult. No exemplo acima, o resultado strresultseria:

strresult="25"

O primeiro "3"caractere não está necessariamente na posição 8 da string strname; da mesma forma, o último não"r" está necessariamente na posição 11. da string. Portanto, ambas as seguintes strings devem render :strnamestrresult="25"

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

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

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

Andrew
fonte

Respostas:

28

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 regex são colocados na matriz especial BASH_REMATCH. O elemento 0 contém a correspondência inteira e 1 contém a correspondência para o primeiro grupo de capturas.

jordanm
fonte
10

Na shsintaxe padrão (isso funcionaria com qualquer versão bashou 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 exprsolução antiga que funcionará em Unices de 35 anos:

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

O velho truque com expré que se o jogo falhar, você obter um status de saída diferente de zero (muito bem), mas você também terá um status de saída diferente de zero se as resoluções cordas voltaram a 0 (como com strname=zz300rzz).

Stéphane Chazelas
fonte
Eu acho que seu fraseado implica incorretamente que isso pode ser feito com versões mais antigas do bash. A expansão dos parâmetros ainda é, obviamente, uma boa abordagem nas conchas modernas.
kojiro
1
@kojiro, entendo o que você quer dizer. A formulação inicial era acompanhar a resposta de Jordan. Eu atualizei minha resposta.
Stéphane Chazelas