awk: extrai uma string de um campo [closed]

2

nos campos de entrada são separados por sinal de pipe:

CCCC|Sess C1|s1 DA=yy07:@##;/u/t/we
DDDDD|Sess C2|s4 DB=yy8:@##;/u/ba

Eu quero obter a saída onde o último campo é alterado (extraído apenas o que está entre first = e: neste campo

A saída esperada

é:

CCCC|Sess C1|yy07
DDDDD|Sess C2|yy8
    
por Chris 10.09.2018 / 14:04

3 respostas

6

padrão awk não é muito bom em extrair dados de campos baseados em padrões. Algumas opções incluem:

  • split() para dividir o texto em um array baseado em delimitadores especificados.
  • match() , que define as variáveis RSTART e RLENGTH para indicar onde a correspondência ocorreu e, em seguida, use subtr() para extrair a parte correspondente.

Então, aqui:

awk -F'|' -v OFS='|' '
  split($3, a, /[=:]/) >= 2 {print $1, $2, a[2]}' < file.txt

Então, retorna a parte entre a primeira e a segunda ocorrência de um = ou : em $3 .

Ou:

awk -F'|' -v OFS='|' '
  match($3, /=[^:]*/) {
    print $1, $2, substr($3, RSTART+1, RLENGTH-1)
  }' < file.txt

O GNU awk tem uma extensão gensub() que traz a funcionalidade do comando sed s para awk :

gawk -F'|' -v OFS='|' '
  $3 ~ /=/ {
    print $1, $2, gensub(/^[^=]*=([^:]*).*/, "\1", 1, $3)
  }' < file.txt

Procura por = seguido por qualquer número de não : s e extrai a parte depois de = . O problema com gensub() é que você não pode dizer facilmente se a substituição foi bem-sucedida ou não, portanto, verifique se $3 contém = primeiro.

com sed :

sed -n 's/^\([^|]*|[^|]*|\)[^=|]*=\([^:|]*\).*//p' < file.txt

com perl :

perl -F'[|]' -lane 'print "$F[0]|$F[1]|$1" if $F[2] =~ /=([^:]*)/' < file.txt
    
por 10.09.2018 / 14:40
4

Eu tentaria

awk -F\|  'BEGIN {OFS="|";} 
   {col=index($3,":"); 
    equ=index($3,"=");
    $3=substr($3,equ+1,col-equ-1); 
    print ; }' se

onde

  • -F\| diz ao awk para usar o | como separador de entrada
  • equ=index($3,"="); get index of = no terceiro campo
  • $3=substr($3,equ+1,col-equ-1); faz a substituição real
por 10.09.2018 / 14:39
0

O primeiro sub remove os primeiros sextos caracteres no campo 3 e o segundo sub remove tudo após o cólon, incluindo.

awk -F\| '{sub(/.{6}/,"",$3)sub(/:.*/,"")}1' OFS=\| file
    
por 10.09.2018 / 23:15