substitui um caractere de uma string que esteja entre a primeira e a segunda pesquisa usando sed ou awk

2

Eu preciso substituir _ (sublinhado) por ? (ponto de interrogação) em um arquivo que contenha endereços de e-mail.

O arquivo se parece com abaixo:

EFT_020034-E015133  20140624    /ACC/[email protected]         SHR    END 
EFT_020034-E015133  20140624    /ACC/[email protected]     SHR    END
EFT_020034-E015133  20140624    /ACC/[email protected]        SHR    END

A saída esperada é:

EFT_020034-E015133  20140624    /ACC/[email protected]         SHR    END 
EFT_020034-E015133  20140624    /ACC/[email protected]     SHR    END
EFT_020034-E015133  20140624    /ACC/[email protected]        SHR    END

Como posso fazer isso em sed ou awk sem afetar outros underscores e apenas o sublinhado entre EMAIL+ (constante) e SHR (constante). O conteúdo alterado deve ser salvo em um novo arquivo.

    
por user73549 25.06.2014 / 11:48

3 respostas

4

o awk fará isso:

$ awk '{ gsub("_", "?", $3) ; print }' < data
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END
EFT_020034-E015133 20140624 /ACC/[email protected] SHR END

Os endereços de e-mail estão no campo 3, então substituímos _ por ? apenas no campo 3, incluindo quando há mais de um _ , usando gsub .

    
por 25.06.2014 / 11:55
3

Com sed você pode fazer:

sed -e :1 -e 's/_\([^+]*@\)/?/;t1'

Substitua _ seguido por uma sequência de caracteres que não sejam + seguidos por @ com ? com a sequência do caractere e repita o processo, desde que corresponda.

Ou apenas entre EMAIL+ e SHR :

sed -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/?/;t1'

Se você quiser considerar apenas as linhas que começam com ^EFT , adicione um -e '/^EFT/!b' para deixar as que não gostam:

sed -e '/^EFT/!b' -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/?/;t1'

Observe que, para uma entrada como:

EFT EMAIL+ foo_bar SHR bar_baz EMAIL+ SHR

Ambos os sublinhados serão substituídos porque estão entre um EMAIL+ e um SHR .

Para evitar isso, você pode fazer algo como:

sed '
  /^EFT/!b # leave the non-EFT lines alone (branch out)
  s/%/%p/g; s/</%l/g; s/>/%r/g; # escape the <>% characters with %
  s/EMAIL+/</g; s/SHR/>/g; # replace EMAIL+ and SHR with < and >
  :1
  s/\(<[^<>]*\)_\([^<>]*>\)/?/; t1
  s/</EMAIL+/g; s/>/SHR/g; # restore EMAIL+ and SHR
  s/%r/>/g; s/%l/</g; s/%p/%/g; # restore the escaped <>%'
    
por 25.06.2014 / 12:35
1
sed '/.*EMAIL+\(.*\)SHR.*/{
    h;s///;y/_/?/;G
    s/\(.*\)\n\(.*EMAIL+\).*SHR/SHR/}'

Isso deve fazer o trabalho de forma bastante confiável - ele substituirá todo _ por ? entre os últimos EMAIL+ ocorridos em uma linha e o último SHR a ocorrer no mesmo e somente nas linhas que contiverem as duas sequências .

    
por 30.06.2014 / 11:33

Tags