Usando cut / awk / sed com dois delimitadores diferentes

2

Eu tenho os seguintes casos:

 [email protected]
 [email protected]
 [email protected]

Estou tentando convertê-los em

 [email protected]
 [email protected]
 [email protected]

Portanto, deve remover tudo, desde o primeiro '_' (incluindo-o) até o @ (não incluindo isso).

Eu tenho algo, mas não funciona corretamente:

Baseado neste tópico: Corte baseado em dois Delimitadores de uma só vez , e este U & Q & A: Divisão da string pela primeira ocorrência de um delimitador .

sed 's/^.*_\([^ ]*\) .*\@\([^$]*\)$/ /' infile

Mas sem sorte. Alguém quer falar sobre isso?

    
por Sten Kin 21.08.2013 / 00:29

6 respostas

3

Supondo que você nunca terá mais de um símbolo @ ,

sed 's/_.*@/@/' file.txt

... deve funcionar.

    
por 21.08.2013 / 00:35
4

Não tenho certeza do que você está realmente fazendo com isso, mas você pode fazer isso com sed :

$ sed 's/\(case\).*\(@test.com\)//' 87529.txt 
[email protected]
[email protected]
[email protected]

Isso reduz efetivamente tudo entre case e @ .

Você pode fazer algo semelhante com awk :

$ awk -F@ '{split($1,a,"_"); print a[1]"@"$2}' 87529.txt 

Também pode ser feito com perl (semelhante à abordagem do evilsoup):

$ perl -p -e 's/_.*@/@/g' 87529.txt 

Ou você pode fazer uso da instalação lookahead de perl :

$ perl -p -e 's/_.*(?=@)//g' 87529.txt 

OBSERVAÇÃO: Lookahead e lookbehind em perl permitem que você inclua strings no padrão regex com as quais você está combinando, sem que elas sejam incluídas na operação que será executada no regex . Pense nelas como versões dinâmicas do cursor ( ^ ) - início de uma linha e dólar ( $ ) - fim da linha. Isso é um pouco menos hacky, depois ter que adicionar o @ de volta, depois de removê-lo.

    
por 21.08.2013 / 01:30
1

Se as linhas puderem conter mais de um @ :

sed 's/^\([^@_]*\)_[^@]*@/@/'

Ou:

awk -F@ -vOFS=@ 'NF >= 2 {sub(/_.*/,"",$1)};1'
    
por 22.08.2013 / 22:05
0

Se o seu shell suporta expansão de parâmetros, você pode fazer algo como

while read line; do
    printf "%s\n" "${line%%_*}@${line#*@}"
done < your_file_here

A expansão ${line%%_*} remove o _ mais à esquerda e tudo o que o segue, enquanto a expansão ${line#*@} remove o @ mais à esquerda e tudo o que o precede.

    
por 21.08.2013 / 10:10
0

do Evilsoup solução parece ser perfeita!

Ainda outra solução usando sed e awk .

sed 's/_/ /g; s/@/ /g' file_name | awk '{ print $1"@"$NF '}

Isso não conta exatamente para eficiência, mas pode ser simples de entender, talvez, quando não se quer mexer com expressões regulares. O código acima faz o seguinte:

  • O primeiro padrão de sed substitui "_" por um espaço em branco.
  • O segundo padrão de sed substitui "@" por um espaço em branco. Então, agora, o conteúdo do arquivo é dividido em várias colunas:

case test.com
case 1_2 test.com
case 1 test.com

  • Finalmente, awk simplesmente imprime a primeira e a última colunas do conteúdo separado. Aqui, NF é um símbolo especial em awk que fornece o número de campos seguidos.
por 21.08.2013 / 08:38
0

Aqui está outro caminho gawk :

gawk -F_ '{if(NF>1){print $1$NF} else {print $NF}}'

Usando _ como um delimitador de campo, informamos gawk para imprimir o primeiro e o último campo se houver mais de um campo e o último campo se houver apenas um único campo.

    
por 21.08.2013 / 14:52