Bash erro de manipulação de string regex

0

Eu tenho um problema com o bash e sua habilidade de correspondência de regex que, por ora, acho que é um bug no bash, mas também poderia ser que eu tenha perdido algo óbvio. Espero que seja o último.

Eu fiz esta função em um script bash para derramar um endereço em campos. Há alguma saída de depuração que será removida eventualmente:

# name number, zip
function split_address
{
    local adr
    adr="$4"
    echo $adr
    local adr_regex
    adr_regex="[ ]*(.*[a-z ]) ([^,][^,]*),[ ]*([^ ]*)[ ]*"
    [[ $adr =~ $adr_regex ]]
    echo 1:X${BASH_REMATCH[1]}X
    echo 2:X${BASH_REMATCH[1]%% }X
    echo 3:Y${BASH_REMATCH[2]}Y
    echo 4:Y${BASH_REMATCH[2]%% }Y
    local x="${BASH_REMATCH[1]}"
    echo 5:X${x%% }X
    local x="${BASH_REMATCH[1]%% }"
    echo 6:X${x}X
    echo 7:X${x%% }X
    eval "$1='${BASH_REMATCH[1]%% }'"
    eval "$2='${BASH_REMATCH[2]%% }'"
    eval "$3='${BASH_REMATCH[3]}'"
}

Eu testo assim:

split_address roadname number zip "  Some string   42 dp ,  1234  "
echo X${roadname}X Y${number}Y Z${zip}Z

Quando chamado, recebo esta saída:

Some string 42 dp , 1234
1:XSome string X
2:XSome string X
3:Y42 dp Y
4:Y42 dpY
5:XSome string X
6:XSome string X
7:XSome stringX
XSome string X Y42 dpY Z1234Z

Primeiro, observe que 4 tem o espaço mostrado em 3 removido. Isto é o que eu quero que aconteça em 2 quando estiver trabalhando em 1. Observe que 5 não obtém o espaço removido, mesmo que isso aconteça na variável x. Esta foi uma tentativa de contornar esse problema. Então eu tentei atribuir a operação de remoção de espaço para a variável x, mas que também falhou (mostrado em 6). Mas remover espaços em x na etapa 7 funcionou mesmo que a linha seja idêntica a 5 e a entrada aparentemente também.

É isso eu fazendo algo estranho ou isso é um bug no bash?

Para referência, estou trabalhando no Ubuntu 14 LTS com a versão bash 4.3.11 (1) -release.

Eu vejo o mesmo comportamento com o Cygwin-x64 com a versão bash 4.1.17 (9-release.

Eu verifiquei que o caractere a ser removido na escritura é um espaço (usando od em source e test-call).

    
por galmok 01.12.2014 / 12:32

2 respostas

2

%% faz glob correspondência, não regex . Isso significa que ${foo%% } removerá a string mais longa correspondente a um caractere de espaço único , que obviamente é apenas um caractere de espaço único, e ${foo%% *} removerá a string mais longa inicial com um caractere de espaço.

Provavelmente, será melhor usar awk para dividir a string em campos.

    
por 01.12.2014 / 13:21
0

Seguindo a solução fornecida por link , corrigi meu script caminho:

echo "8:X${BASH_REMATCH[1]%"${BASH_REMATCH[1]##*[![:space:]]}"}X"
eval "$1='${BASH_REMATCH[1]%"${BASH_REMATCH[1]##*[![:space:]]}"}'"

Esta é uma manipulação de cadeia dupla e a primeira parte interna remove tudo, exceto os espaços à direita. Essa string é usada para cortar os mesmos espaços no final da string original.

    
por 01.12.2014 / 13:39