J'ai un fichier au format suivant
Colonne1 Colonne2 str1 1 str2 2 str3 3
Je veux que les colonnes soient réorganisées. J'ai essayé ci-dessous la commande
couper -f2,1 fichier.txt
La commande ne réorganise pas les colonnes. Une idée pourquoi ça ne marche pas?
Je vous remercie.
cut
ne pas prendre en charge cette commande de réorganisation intuitive. Quoi qu'il en soit, une autre astuce: vous pouvez utiliserawk
les options-FS
et-OFS
pour utiliser des séparateurs de champs d'entrée et de sortie personnalisés (comme-d
et--output-delimiter
pourcut
).FS
est une option,OFS
est une variable. egawk -v OFS=";" -F"\t" '{print $2,$1}'
| sed 's/\r//' |
avant de passer àawk
awk '{print $4 "\t" $2 "\t" $6 "\t" $7}' file
Vous pouvez également combiner
cut
etpaste
:via les commentaires: Il est possible d'éviter les bashismes et de supprimer une instance de coupe en faisant:
la source
cut
fonctionne très bien pour les colonnes de longueur variable tant que vous avez un séparateur de colonne unique.bash
isms et de supprimer une instance decut
en faisant:paste file.txt file.txt | cut -f2,3
en utilisant juste la coque,
la source
"$col2"
et"$col1"
- il pourrait y avoir des métacaractères shell ou d'autres manigances dans les données.Vous pouvez utiliser Perl pour cela:
L'avantage d'exécuter perl est que (si vous connaissez Perl) vous pouvez faire beaucoup plus de calculs sur F que de réorganiser les colonnes.
la source
perl -ae print
fonctionne commecat
pour moiUtilisation
join
:Remarques:
-t $'\t'
Dans GNUjoin
le plus intuitif-t '\t'
sans les$
échecs, ( coreutils v8.28 et antérieurs?); c'est probablement un bogue qu'une solution de contournement comme$
devrait être nécessaire. Voir: unix join separator char .join
a besoin de deux noms de fichiers, même s'il n'y a qu'un seul fichier en cours de traitement. Utiliser deux fois le même nom permet d'join
effectuer l'action souhaitée.Pour les systèmes à faibles ressources, il
join
offre une empreinte plus petite que certains des outils utilisés dans d'autres réponses:la source
Je viens de travailler sur quelque chose de très similaire, je ne suis pas un expert mais je pensais partager les commandes que j'ai utilisées. J'avais un csv multi-colonnes dont je n'avais besoin que de 4 colonnes, puis je devais les réorganiser.
Mon fichier était pipe '|' délimité mais qui peut être échangé.
Certes, c'est vraiment rugueux et prêt, mais il peut être modifié pour convenir!
la source
Utilisation de sed
Utilisez sed avec les sous-expressions imbriquées des expressions régulières de base pour capturer et réorganiser le contenu de la colonne. Cette approche est la mieux adaptée lorsqu'il y a un nombre limité de coupes pour réorganiser les colonnes, comme dans ce cas.
L'idée de base est d'entourer les parties intéressantes du motif de recherche avec
\(
et\)
, qui peuvent être lues dans le motif de remplacement avec\#
où#
représente la position séquentielle de la sous-expression dans le motif de recherche.Par exemple:
donne:
Le texte en dehors d'une sous-expression est analysé mais pas conservé pour la lecture dans la chaîne de remplacement.
Bien que la question n'ait pas abordé les colonnes à largeur fixe, nous en discuterons ici car c'est une mesure digne de toute solution posée. Pour simplifier, supposons que le fichier soit délimité par des espaces bien que la solution puisse être étendue pour d'autres délimiteurs.
Espaces réduits
Pour illustrer l'utilisation la plus simple, supposons que plusieurs espaces peuvent être réduits en espaces simples et que les valeurs de la deuxième colonne se terminent par EOL (et non par un espace).
Fichier:
Transformer:
Préservation des largeurs de colonne
Étendons maintenant la méthode à un fichier avec des colonnes de largeur constante, tout en permettant aux colonnes d'être de largeurs différentes.
Fichier:
Transformer:
Enfin, bien que l'exemple de la question n'ait pas de chaînes de longueur inégale, cette expression sed prend en charge ce cas.
Fichier:
Transformer:
Comparaison avec d'autres méthodes de réorganisation des colonnes sous shell
Étonnamment pour un outil de manipulation de fichiers, awk n'est pas bien adapté pour couper d'un champ à la fin d'un enregistrement. Dans sed, cela peut être accompli en utilisant des expressions régulières, par exemple
\(xxx.*$\)
oùxxx
est l'expression correspondant à la colonne.L'utilisation de sous-shell coller et couper devient délicate lors de l'implémentation de scripts shell internes. Le code qui fonctionne à partir de la ligne de commande ne parvient pas à être analysé lorsqu'il est introduit dans un script shell. Au moins c'était mon expérience (qui m'a poussé à cette approche).
la source
Extension de la réponse de @Met, également en utilisant Perl:
Si l'entrée et la sortie sont délimitées par TAB:
Si l'entrée et la sortie sont séparées par des espaces:
Ici,
-e
indique à Perl de rechercher le code en ligne, plutôt que dans un fichier de script séparé,-n
lit l'entrée 1 ligne à la fois,-l
supprime le séparateur d'enregistrement d'entrée (\n
sur * NIX) après avoir lu la ligne (similaire àchomp
), et ajoute la sortie séparateur d'enregistrement (\n
sur * NIX) à chacunprint
,-a
divise la ligne d'entrée sur les espaces en tableau@F
,-F'\t'
en combinaison avec-a
divise la ligne d'entrée sur les TAB, au lieu des espaces en tableau@F
.@F[1, 0]
est le tableau composé des 2e et 1er éléments du tableau@F
, dans cet ordre. N'oubliez pas que les tableaux en Perl sont indexés à zéro, tandis que les champs danscut
sont indexés à 1. Les champs de@F[0, 1]
sont donc les mêmes que ceux decut -f1,2
.Notez qu'une telle notation permet une manipulation plus flexible de l'entrée que dans certaines autres réponses publiées ci-dessus (ce qui est bien pour une tâche simple). Par exemple:
la source