Padrão de correspondência GNU e substitui o número exato de caracteres

1

Esta pergunta pode ter sido listada, mas não consegui encontrar um hit exato.

Estou tentando percorrer um arquivo, corresponder a um padrão e substituí-lo por outra coisa. No entanto, existem outras ocorrências do padrão, mas eu preciso substituir apenas aquelas que têm 17 caracteres de comprimento.

Exemplo:

Conteúdo:

dlkfhfd|fedfe|dfwe3f347fde|3745978|dlkfhr**|376663781736102|**fedfe|dfwe3f347fde

Expectativa:

dlkfhfd|fedfe|dfwe3f347fde|3745978|dlkfhr**|37xxxxxxxxxxxxx|**fedfe|dfwe3f347fde

Progresso: Consegui combinar a expressão com o padrão regexp: **\|37[0-9]{13}\|**

No entanto, se eu colocá-lo em um sed , apenas substitui tudo no arquivo.

sed -e s/\|37[0-9]{13}\|/\|37xxxxxxxxxxxxx\|/g

Minha versão sed é 4.2.2

    
por Ishan 26.04.2018 / 20:49

1 resposta

3

Sua expressão regular é uma mistura entre expressão regular básica e estendida.

Como uma expressão regular estendida (usando {13} e \| como um canal literal):

sed -E 's/\|37[0-9]{13}\|/|37xxxxxxxxxxxxx|/g'

Como alternativa, como uma expressão regular básica (usando \{13\} e | como um canal literal):

sed 's/|37[0-9]\{13\}|/|37xxxxxxxxxxxxx|/g'

Isso transforma sua string de exemplo em

dlkfhfd|fedfe|dfwe3f347fde|3745978|dlkfhr**|37xxxxxxxxxxxxx|**fedfe|dfwe3f347fde

Observe também que não há necessidade de escapar do | na parte de substituição da expressão, já que essa parte nunca é interpretada como uma expressão regular.

Em awk :

awk -F '|' -vOFS='|' '
    {
        for (i=1; i<=NF; ++i))
            if (length($i)==15 && match($i,"^37[0-9]"))
                $i="37xxxxxxxxxxxxx"
        print 
     }'

Alguém poderia ter usado gsub() aqui, mas isso teria tornado mais ou menos idêntico à solução sed e, portanto, chato.

Isso tem o benefício de que a substituição também ocorra no primeiro ou no último campo, mesmo que esse campo não tenha sido delimitado por | em ambas as extremidades.

    
por 26.04.2018 / 20:58