Une question sur awk

9

Ok, puisque c'est une question complexe, je vais l'expliquer clairement. J'ai obtenu un contenu de fichier comme indiqué ci-dessous:

$ 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}

La sortie que je veux

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

Tout d'abord, j'essaie de retirer la dernière colonne de la File1et de l'imprimer par sed 's/[{}//g' File1 > File3

Après cela, je copie tout le contenu d' File1un nouveauFile4

cp File1 File4

Après cela, je remplace les données à l'intérieur du File4par les File3données (signifie les données sans parenthèse une " File1dernière colonne celle-là")

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

La sortie devrait être comme ceci

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

Enfin, j'essaye

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

Mais le résultat n'est pas sorti comme indiqué comme je le souhaite, seules les données similaires MNB sont toutes répertoriées, d'autres ne sont pas apparues (fichier une dernière colonne de données),

heng960407
la source
Utilisez-vous gnu awk?
123
Je ne sais pas ce que tu veux dire. Mais je suis juste un nouveau débutant pour toucher à awk. C'est la tâche que je dois faire, j'essaie de mon mieux de lentement une étape à une étape pour le faire en fonction de ma compréhension de awk.
heng960407
1
type awk --version, quel est le résultat?
123
2
Veuillez modifier votre titre en quelque chose de plus spécifique à votre problème. Cela facilitera la recherche d'autres personnes qui ont des questions similaires à l'avenir. Pour le moment, "Une question sur awk" est très générale.
Tom Fenech

Réponses:

16

Je ne sais pas pourquoi vous copiez les choses à gauche et à droite. La chose simple est

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

J'ai mis le -au début et ;à la fin.

Entre les deux, nous imprimons

  • $2 parce que nous le voulons tel quel.
  • une sous-chaîne de $5, qui est la chaîne sans le premier et le dernier caractère. Nous sautons le premier caractère en commençant à la position 2 (awk a toujours été étrange à ce sujet) et omettons le dernier caractère en sélectionnant uniquement une sous-chaîne qui est deux caractères plus courte que l'original$5
  • le +parce que nous voulons
  • et alors $4

Cependant, je ne sais pas si toutes ces fonctions de chaîne sont spécifiques à GNU awk.

Bananguin
la source
substr(string, 2)retourne la sous - chaîne à partir du second caractère, comme cut -c2-, tail -n +2, sed '2,$'... Ce qui est si étrange à ce sujet?
Stéphane Chazelas
3
Cette commande est standard et fonctionnerait même avec l'original awkdes années 70.
Stéphane Chazelas
@ StéphaneChazelas: Ah, je vous attendais :-) Habituellement, nous commençons à compter à 0, ce qui signifie que l'index 2 est la troisième position, mais ici la deuxième position est à l'index 2. Merci d'avoir clarifié la question GNU restante.
Bananguin
@Bananguin, dans le shell Unix et les utilitaires comme indiqué dans les quelques exemples ci-dessus, nous commençons à 1, pas à 0. Les exceptions les plus notables sont les tableaux de ksh et $ {var: offset} (tous deux copiés par bash). Tous les autres tableaux de shell commencent à 1. Voir aussi Y a-t-il une raison pour laquelle le premier élément d'un tableau Zsh est indexé par 1 au lieu de 0?
Stéphane Chazelas
7

Avec sed

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

Et la variation awk

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

Travail TXR facile :

$ 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 ;

Utilisation de la macro awk TXR Lisp pour translittérer la solution Awk:

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

Les champs sont dans la fliste et l'indexation est basée sur zéro.

Kaz
la source
1
+1 pour le look éclatant et le plus cristallin! Ce langage DOIT concurrencer en pcg (code de programmation golf)
Archemar
@Archemar TXR n'est pas très compétitif dans le golf, car il existe des langages spécialisés conçus pour cela, comme assigner des fonctions à des personnages individuels, qui peuvent ensuite être enchaînés pour obtenir la composition.
Kaz
1
@Kaz Y a-t-il un tutoriel TXR quelque part? La page de manuel semble plutôt énorme. Comment fonctionne-t-il par rapport à awk?
bli
1
@bli GNU Awk est quelque chose comme au moins 30 fois plus rapide lors du fractionnement de champ de base à travers un gros fichier que la macro TXR awk, qui comprend plus de 220 lignes de code interprété , y compris la boucle globale pour le traitement des sources d'entrée en enregistrements et champs.
Kaz
3

L'utilisation de awk est plus simple lorsque les $1,$2,...champs contiennent déjà les chaînes exactes avec lesquelles vous souhaitez travailler. Le séparateur de champ, s'il contient plusieurs caractères, est interprété comme une expression régulière. Nous n'avons pas besoin de faire d'opérations de recherche et de remplacement ou de sous-chaîne pour se débarrasser des {accolades}. Nous les comptons simplement comme faisant partie du délimiteur.

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

Utiliser printfau lieu de printrend également un peu plus facile de voir comment la chaîne sera formatée, mais si vous voulez avoir à la print "-"$2,$5" + "$4";"place de printf("-%s %s + %s ;\n", $2, $5, $4), c'est une option.

Rayon
la source