Como extrair colunas antes e depois de uma ocorrência de cadeia

2

Eu tenho um arquivo de texto. Parece que:

www.ac.com has address 6.1.1.146 www.ac.com is an alias for ac.com. www.ac.com is an alias for ac.com.
www.ba.net is an alias for www-bn.gs.ba.com. www-bn.gs.ba.com has address 11.28.11.4 ;; connection timed out; no servers could be reached

Eu quero extrair a coluna antes e depois de has address e separá-las por vírgula. Então eu quero pegar:

www.ac.com,6.1.1.146
www-bn.gs.ba.com,11.28.11.4

Como fazer isso? Eu tentei awk '{print $1,$4}' myfile > newfile , mas não funcionou bem, pois nem sempre é o caso o que eu quero é nas colunas 1 e 4. As colunas de interesses podem variar, mas sempre separadas por has address .

    
por user9371654 31.07.2018 / 12:33

4 respostas

3

Usando grep e sed :

grep -o '[^ ]* has address [^ ]*' | sed 's/ has address /,/'

Eu gosto deste, porque é muito fácil.

Explicação :

grep produzirá apenas a parte correspondente ( -o ) de cada linha que encontrar o seguinte padrão:

  • qualquer caractere que não seja um espaço ( [^ ]* ) seguido por has address seguido por qualquer caractere que não seja um espaço ( [^ ]* ).

sed simplesmente substituirá has address por ,

    
por 31.07.2018 / 13:04
3

Em sed :

sed -r 's/(.* |^)([^ ]*) has address ([^ ]*)( .*|$)/,/' myfile > newfile

Explicação

  • sed -r 's/foo/bar/' myfile > newfile : use sed com "expressões regulares estendidas" ( -r ), portanto, não precisamos escapar da captura de grupos () abaixo. Substitua as ocorrências de foo por bar . Leia de myfile e escreva para newfile .
  • (.* |^)([^ ]*) has address ([^ ]*)( .*|$) : procure a string has address , precedida e seguida por um espaço. Antes e depois disso, deve ser uma string que não inclua espaços, que devemos capturar em um grupo ([^ ]*) . Antes, a palavra principal deve ser um espaço (precedido por qualquer um, .* ) ou o início da linha, ou seja, (.* |^) . Depois, a palavra a seguir deve ser um espaço (seguido por qualquer, .* ) ou o final da linha, ou seja, ( .*|$) .
  • , : a expressão acima captura a linha inteira, então substitua-a pelo segundo e terceiro grupos de captura, ou seja, a palavra antes e depois de has address .
por 31.07.2018 / 12:55
2
perl -nE '/(\S+) has address (\S+)/ and say "$1,$2"' x
    
por 31.07.2018 / 13:55
0

Em awk :

awk -v OFS=, '
  {
    for(i=1;i<NF;i++){
      j=i+1;
      if ($i=="has" && $j=="address") {
        domain=i-1;
        ip=i+2;
        print $domain,$ip;
        break;
      }
    }
  }'

Faz um loop pelos campos e, se encontrar "has" e o próximo campo for "address", imprimirá os campos antes e depois com , como separador de campo de saída.

    
por 31.07.2018 / 12:59