${TEST#...}
corresponde à string mais curta, que é z seguida por espaços zero. Você precisa de ${TEST##...}
, a correspondência mais longa.
Dado:
$ shopt -s extglob
$ TEST=" z abcdefg";echo ">>${TEST#*( )z*( )}<<"
>> abcdefg<<
Por que existe um espaço antes da letra 'a'? Eu esperaria que o segundo *( )
correspondesse ao espaço, mas não parece ser necessário.
Eu esperava o equivalente a:
$ echo ">>$(echo -n "${TEST}" | perl -pe "s/^ *z *//g")<<"
>>abcdefg<<
O segundo *( )
corresponde se eu especificar o próximo caractere seguinte (que é 'a'):
$ shopt -s extglob
$ TEST=" z abcdefg";echo ">>${TEST#*( )z*( )a}<<"
>>bcdefg<<
Versão do Bash: GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Isso se deve à interação entre a remoção de substring não-gulosa e o tipo de padrão que você está usando.
No manual do bash ,
?(pattern-list)
Matches zero or one occurrence of the given patterns.
*(pattern-list)
Matches zero or more occurrences of the given patterns.
+(pattern-list)
Matches one or more occurrences of the given patterns.
De minha explicação favorita sobre a manipulação de string do bash,
${string#substring}
Deletes shortest match of
$substring
from front of$string
.
${string##substring}
Deletes longest match of
$substring
from front of$string
.
Então, quando você especifica ${TEST#*( )z*( )}
, você está dizendo: "Por favor, apague a subseqüência mais curta que tenha zero ou mais espaços, um z
, depois zero ou mais espaços.
A correspondência no último espaço é maior do que a correspondência sem ele, portanto, o último espaço nunca é correspondido.
Para corrigir isso, você pode usar ${TEST##*( )z*( )}
para corresponder ao prefixo mais longo que termina com zero ou mais espaços ou ${TEST#*( )z+( )}
para corresponder ao prefixo mais curto que termina com um ou mais espaços (que é funcionalmente equivalente a corresponder ao prefixo mais curto terminando com um espaço).
Como você deseja imitar é um regex (perl), use um regex
não um pattern
:
$ test=" z abcdefg"
$ regex='^ *z *(.*)'
$ [[ $test =~ $regex ]]
$ echo ">>${BASH_REMATCH[1]}<<"
>>abcdefg<<
A regex é uma regex estendida, não uma PCRE completa.