Uma pergunta sobre awk

9

Ok, já que essa é uma pergunta complexa, vou explicar claramente. Eu tenho um conteúdo de arquivo mostrado como abaixo:

$ Cat File1 
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}

A saída que eu quero

-Cool MNB +  POP ;
-Cool MNB  + POP ;
-Cool MNB  + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD +POP ;

Em primeiro lugar, tento retirar a última coluna da File1e imprimi-la sed 's/[{}//g' File1 > File3

Depois disso, copio todo o conteúdo de File1para um novoFile4

cp File1 File4

Depois disso, substituo os dados dentro dos File4com os File3dados (significa os dados sem colchete uma " File1última coluna que uma")

awk 'FNR==NR{a[NR]=$1;next}{$5=a[FNR]}1' File3 File4 >>File5 

A saída deve ser assim

ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP TBMKF
ABC Cool Lol POP YUKER
ABC Cool Lol POP EFEFVD

Finalmente tento

awk -F " '{print - $2,$5 +,$4 ";"}‘ File5

Mas o resultado não saiu como mostrado como eu quero, apenas os dados similares MNB estão todos listados, outros não apareceram (Arquive dados de uma última coluna),

heng960407
fonte
Você está usando o gnu awk?
123
Não sei bem o que você quer dizer. Mas eu sou apenas um novato em tocar o awk. Esta é a tarefa que preciso fazer. Tento o meu melhor para ir lentamente um passo a um passo para fazer isso com base na minha compreensão do awk.
precisa saber é o seguinte
1
tipo awk --version, qual é o resultado?
123
2
Altere seu título para algo mais específico ao seu problema. Isso tornará mais fácil para outras pessoas que tiverem perguntas semelhantes no futuro. No momento "Uma pergunta sobre o awk" é muito geral.
21416 Tom Fenech

Respostas:

16

Não sei por que você está copiando as coisas da esquerda para a direita. A coisa simples é

awk '{print "-" $2, substr($5,2,length($5)-2), "+", $4, ";"}' File1

Coloquei o -no início e ;no final.

Entre nós, imprimimos

  • $2 porque nós queremos como é.
  • uma substring de $5, que é a sequência sem o primeiro e o último caractere. Ignoramos o primeiro caractere começando na posição 2 (o awk sempre foi estranho sobre isso) e deixamos de fora o último caractere apenas selecionando uma substring com dois caracteres mais curtos que o original$5
  • o +porque nós queremos
  • e depois $4

No entanto, não tenho certeza se todas essas funções de string são específicas para o GNU awk.

Bananguin
fonte
substr(string, 2)retorna a substring a partir do segundo personagem, como cut -c2-, tail -n +2, sed '2,$'... O que é tão estranho nisso?
Stéphane Chazelas
3
Esse comando é padrão e até funcionaria com o original awkdos anos 70.
Stéphane Chazelas 15/09/16
@ StéphaneChazelas: Ah, eu estive esperando por você :-) Normalmente começamos a contar em 0, o que significa que o índice 2 é a terceira posição, mas aqui a segunda posição está no índice 2. Obrigado por esclarecer a questão restante do GNU.
Bananguin 15/09/16
@Banguanguin, no shell e utilitários do Unix, como mostrado nos poucos exemplos acima, começamos com 1, e não 0. As exceções mais notáveis ​​são as matrizes do ksh e $ {var: offset} (ambos copiados pelo bash). Todas as outras matrizes shell começam em 1. Consulte também Existe uma razão pela qual o primeiro elemento de uma matriz Zsh é indexado por 1 em vez de 0?
Stéphane Chazelas 15/09/16
7

Com sed

sed '
    s/\S\+\s/-/
    s/\(\S\+\s\)\{2\}{\(\S\+\)}/\2 + \1;/
    ' File1

E variação awk

awk -F"[[:blank:]{}]+" '{print "-" $2, $5, "+", $4}' ORS=" ;\n" File1
Costas
fonte
6

Trabalho fácil de TXR :

$ txr -c '@(repeat)
@a @b @c @d {@e}
@(do (put-line `-@b @e + @d ;`))
@(end)' -
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}
[Ctrl-D][Enter]
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD + POP ;

Usando a macro TXR Lisp awk para transliterar a solução Awk:

 txr -e '(awk (t (prn `-@[f 1] @{[f 4] [1..-1]} + @[f 3] ;`)))'

Os campos estão na flista e a indexação é baseada em zero.

Kaz
fonte
1
+1 para o visual lispiest e choro! Que competem linguagem deve em PCG (programação de golfe código)
Archemar
O @Archemar TXR não compete muito bem no golfe, porque há linguagens especializadas projetadas para aquilo que atribui funções a caracteres individuais, que podem ser combinadas para obter composição.
Kaz
1
@Kaz Existe um tutorial TXR em algum lugar? A página de manual parece bastante grande. Como ele se compara ao awk?
bli
1
O @bli GNU Awk é algo pelo menos 30 vezes mais rápido na divisão básica de campos em um arquivo grande que a macro TXR awk, que contém mais de 220 linhas de código interpretado , incluindo o loop geral para processar fontes de entrada em registros e campos.
Kaz
3

Usar o awk é mais fácil quando os $1,$2,...campos já contêm as strings exatas com as quais você deseja trabalhar. O separador de campos, se contiver mais de um caractere, será interpretado como uma expressão regular. Não precisamos fazer nenhuma operação de pesquisa e substituição ou substring para nos livrarmos dos {chaves entre chaves}. Nós apenas os contamos como parte do delimitador.

awk -F'[ {}]+' '{printf("-%s %s + %s ;\n", $2, $5, $4)}'

Usar em printfvez de printtambém facilita um pouco a visualização de como a string será formatada, mas se você quiser, em print "-"$2,$5" + "$4";"vez de printf("-%s %s + %s ;\n", $2, $5, $4), essa é uma opção.

Raio
fonte