Comment puis-je combiner des valeurs de deux colonnes?


11

J'ai un fichier au format suivant:

$ cat /tmp/raw
2015-01   5000   1000
2015-02   6000   2000
2015-03   7000   3000

Maintenant, ce que je veux, c'est obtenir la valeur combinée des colonnes 2 et 3 dans chaque ligne afin que les résultats soient les suivants:

2015-01   6000
2015-02   8000
2015-03   9000

J'ai essayé cela, mais il ne montre que la dernière valeur du fichier comme la valeur 2015-03.

Réponses:


11

Vous pouvez essayer d'utiliser awk:

awk '{ print $1, $2 + $3; }' /tmp/raw

Le résultat sera (je suppose que la valeur pour 2015-03 devrait être 10000):

2015-01 6000
2015-02 8000
2015-03 10000

1
Je ne peux pas croire que j'ai obtenu la réponse aussi rapidement: O, je n'ai jamais reçu une réponse aussi rapide sur aucun autre forum :) merci la commande a parfaitement fonctionné :)
Syed Jahanzaib

@SyedJahanzaib, Si cette réponse a résolu votre problème, veuillez prendre un moment et l' accepter en cliquant sur la coche à gauche. Cela marquera la réponse à la question et c'est la façon dont les remerciements sont exprimés sur les sites Stack Exchange.
terdon

désolé j'ai oublié de marquer la réponse. et merci à tous les autres pour leur temps précieux et leurs réponses, ils m'ont aussi aidé à apprendre à atteindre des objectifs avec différentes méthodes :)
Syed Jahanzaib

@SyedJahanzaib, bien que j'ai obtenu un joli badge pour cette réponse, je pense que la réponse de terdon est plus précise et complète.
taliezin

16

Voici quelques façons:

  1. Une autre approche awk

    awk '{$2+=$3;}NF--' file
    
  2. Perl

    perl -lane 'print "$F[0] ",$F[1]+$F[2]' file
    

    ou

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. Shell (beaucoup plus lent / moins efficace que ce qui précède)

    while read a b c; do echo "$a $((b + c))"; done < file
    

2
$2+=$3peut être plus génial.
123

@ User112638726 en effet, il l'est. Merci.
terdon

3
Vous pouvez également utiliser awk '{$2+=$3}NF--'afin qu'il n'y ait pas encore un champ vide 3 qui traîne. Bien que ce soit juste ma préférence, et c'est trop similaire pour poster comme réponse seule :)
123

1
@ User112638726 maintenant que je ne m'en étais même pas rendu compte. Beaucoup mieux, merci!
terdon

J'ai écrit ça pour toi. Notez comment non seulement parvient en sedquelque sorte à comprendre les champs - même à définir des champs à la volée et des champs avec des champs - mais, comme c'est apparemment le cas, le concept entier de correspondance d'expressions Unix est en fait basé sur la division d'une chaîne en champs selon un schéma ! Qui savait?
mikeserv

5
sed 's/[^ ]* */[&]P/;s//&+pc/3'|dc

... impressions ...

2015-01   6000
2015-02   8000
2015-03   10000

Donc, ci-dessus, je déclare une expression régulière qui définit une étendue de champ qui se compose d'une séquence unique de *longueur variable de caractères qui ^ne sont pas <espace> suivie immédiatement d'une séquence unique de *longueur variable de caractères qui sont <espace> . Cette déclaration est appliquée à sedl'espace de modèle de, qui est une chaîne délimitée (par défaut) par chaque \ncaractère ewline qui se produit en entrée, et qui est récursivement remplacée (par défaut) par la suivante pour chaque occurrence de celui-ci.

L'interface de cette déclaration est double et à chaque niveau est entièrement réglementée et spécifiée par au moins un comité international de normalisation officiel de l'IEEE pour assurer une application prévisible de la sedsyntaxe de commande. sedLa syntaxe de l'API , par exemple, est appliquée dans ce cas avec la commande d' /adresse (qui est toujours le premier composant de toute commande d'ubstitution) , mais son contenu est interprété par une API plus basique comme un sous-ensemble de celui spécifié pour le dans la bibliothèque C standard ./sed s///regcomp()

Je peux faire ces déclarations en toute confiance, car ce sedn'est pas seulement un programme, mais plutôt l'exécutable compilé nommé sedsur ma machine de type Unix est une implémentation de l'application bien définie, historiquement établie et contrôlée par les normes de l' sed application régulière de mon système. bibliothèques de correspondance d'expression.


De la sedspécification:

L' sedutilitaire doit prendre en charge les BRE décrits dans XBD Basic Regular Expressions ...

... où l'on trouve ...

Les deux BREs et ERE sont pris en charge par l'interface de correspondance d'expression régulière dans le volume Interfaces système de POSIX.1-2008 sous regcomp(), regexec()et les fonctions connexes.

Une application qui appelle lui regcomp()présentera une chaîne de motif et ...

... [la] regcomp()fonction doit compiler l'expression régulière contenue dans la chaîne pointée par l' argument pattern et placer les résultats dans la structure preg ...

Pour agir sur ce point, ladite application ferait alors référence à regcomp()la fonction compagnon de ...

... [la] regexec()fonction compare la chaîne terminée par un caractère nul spécifiée par string avec l'expression régulière compilée preg initialisée par un appel précédent à regcomp()...

... regexec()doit remplir les éléments d'un [tableau] avec des décalages des sous-chaînes de chaîne qui correspondent aux \(sous \)- expressions entre parenthèses du motif ... le motif lui-même compte comme une sous-expression ...

... [la] regexec()fonction doit remplir tous les éléments nmatch de pmatch , où nmatch et pmatch sont fournis par l'application, même si certains éléments de pmatch ne correspondent pas à des sous-expressions dans le motif .


Et donc quand je le fais ...

/[^ ]* */

... compile d'sed abord l'expression régulière et stocke les résultats en mémoire, puis applique ensuite l'automate compilé qui y est stocké au contenu de mon espace modèle autant de fois que nécessaire pour exécuter ma commande. Chaque fois qu'il le fait, le résultat est un tableau d'un ou plusieurs champs délimités par des valeurs nulles comme délimité au niveau des décalages renvoyés par .regexec()

Et quand je le fais ...

//

... pour indiquer que l'expression régulière définie le plus récemment doit être utilisée, sedil suffit d'appeler à regexec()nouveau en réutilisant l'expression régulière précompilée, mais éventuellement en l'appliquant cette fois à un argument de chaîne modifié ou en appliquant de nouveaux paramètres nmatch comme commande I.

Plus précisément encore ...

  • s/[^ ]* */[&]P/
    • remplacer la première occurrence de motif dans l'espace de motif par un [crochet carré gauche, puis &lui-même, puis un ]crochet carré droit suivi d'un Pcaractère.
  • s//&+pc/3
    • appliquez à nouveau la dernière expression régulière utilisée à l'espace de motif actuel et remplacez la 3troisième occurrence de motif dans l'espace de motif par &elle-même suivie de la chaîne ajoutée +pc.

Et donc pour chaque ligne d' sedentrée, il écrit dans sa sortie standard, étant donné vos données d'exemple:

[2015-01   ]P5000   1000+pc
[2015-02   ]P6000   2000+pc
[2015-03   ]P7000   3000+pc

Cela peut sembler étrange, mais la dccalculatrice cite des chaînes dans son entrée entre crochets, et la Pcommande imprimera à la fois le haut de la pile sans ajouter de ligne \nélectronique et ensuite la fera disparaître de la pile d'entrée.

Et donc, en utilisant la première ligne comme exemple, dccela fera:

  • [2015-01 ]P
    • Print et pop le haut de la pile
  • 5000
    • Poussez le numéro en 5000haut de la pile et poussez tous les éléments actuellement sur la pile (maintenant aucun) vers le bas.
  • 1000
    • idem, mais cette fois le nombre 5000 en haut de la pile principale est poussé vers le bas par un, et devient le deuxième élément de la pile.
  • +
    • Ajoutez les deux premiers chiffres de la pile ensemble, sortez les deux de la pile et poussez la somme en haut de la pile.
    • Il en résulte une pile composée uniquement du nombre 6000.
    • Il s'agit d'une erreur de syntaxe si l'un des deux premiers éléments de la pile est une [chaîne ].
  • p
    • pimprimer le haut de la pile suivi d'une ligne \nélectronique ajoutée sans la faire sauter hors de la pile.
  • c
    • capprendre la pile

Je crois que cela fonctionne, mais je ne peux pas l'analyser. Dans l'ensemble, vous configurez un ajout pour DC. Le premier motif est logique. Je pense que cela correspond à la date et aux espaces de fin, mais je ne comprends pas ce que cela fait à l'intérieur des crochets de classe de caractères ([&]). Ce serait génial si vous épeliez celui-ci.
Joe

1
@Joe - mieux?
mikeserv

Hou la la! Cela a beaucoup plus de sens (et me montre un tas de choses sur lesquelles je dois en savoir plus.) En particulier, je n'avais jamais remarqué l'utilisation de // pour réutiliser le motif actuel. C'est le genre de chose que vous lisez et oubliez jusqu'à ce que vous rencontriez un exemple réel. Merci beaucoup. Cela m'a fait rire de voir combien de puissance pouvait être contenue dans une minuscule commande et combien il fallait pour l'expliquer.
Joe

@Joe - eh bien ... peut-être que je suis allé un peu
trop loin
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.