
Preciso substituir _
(sublinhado) por ?
(ponto de interrogação) em um arquivo que contém 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 emsedouestranhosem afetar outros sublinhados e apenas o sublinhado entre EMAIL+
(constante) e SHR
(constante). O conteúdo alterado deve ser salvo em um novo arquivo.
Responder1
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, portanto substituímos _
por ?
apenas no campo 3, inclusive quando houver mais de um _
, usandogsub
.
Responder2
Com sed
você poderia fazer:
sed -e :1 -e 's/_\([^+]*@\)/?\1/;t1'
Isso é substituir _
seguido por uma sequência de não- +
caracteres seguida por @
com ?
a sequência de caracteres e repetir o processo desde que corresponda.
Ou fazer isso apenas entre EMAIL+
e SHR
:
sed -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;t1'
Se você quiser considerar apenas as linhas que começam com ^EFT
, você pode adicionar um -e '/^EFT/!b'
para deixar de lado aquelas que não gostam:
sed -e '/^EFT/!b' -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;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 an EMAIL+
e a SHR
.
Para evitar isso, você poderia 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/\(<[^<>]*\)_\([^<>]*>\)/\1?\2/; t1
s/</EMAIL+/g; s/>/SHR/g; # restore EMAIL+ and SHR
s/%r/>/g; s/%l/</g; s/%p/%/g; # restore the escaped <>%'
Responder3
sed '/.*EMAIL+\(.*\)SHR.*/{
h;s//\1/;y/_/?/;G
s/\(.*\)\n\(.*EMAIL+\).*SHR/\2\1SHR/}'
Isso deve fazer o trabalho de maneira bastante confiável - substituirá tudo _
entre ?
o último EMAIL+
ocorrido em uma linha e o último SHR
ocorrido na mesma e somente nas linhas que contêm ambas as strings.