J'ai plus de 1000 lignes dans un fichier. Le fichier commence comme suit (numéros de ligne ajoutés):
Station Name
Station Code
A N DEV NAGAR
ACND
ABHAIPUR
AHA
ABOHAR
ABS
ABU ROAD
ABR
J'ai besoin de convertir cela en un fichier, avec des entrées séparées par des virgules en joignant toutes les deux lignes. Les données finales devraient ressembler à
Station Name,Station Code
A N DEV NAGAR,ACND
ABHAIPUR,AHA
ABOHAR,ABS
ABU ROAD,ABR
...
Ce que j’essayais, c’est d’essayer d’écrire un script shell puis de echo
les séparer par une virgule. Mais j'imagine qu'une solution simple et efficace ferait l'affaire ici sed
/ awk
.
Des idées?
Réponses:
Utilisez simplement
cat
(si vous aimez les chats ;-)) etpaste
:Explication:
paste
lit dans un certain nombre de fichiers et colle ensemble les lignes correspondantes (ligne 1 du premier fichier avec ligne 1 du deuxième fichier, etc.):Au lieu d'un nom de fichier, nous pouvons utiliser
-
(tiret).paste
prend la première ligne de file1 (qui est stdin). Ensuite, il veut lire la première ligne de file2 (qui est aussi stdin). Cependant, puisque la première ligne de stdin a déjà été lue et traitée, ce qui attend maintenant sur le flux d'entrée est la deuxième ligne de stdin, quipaste
se colle heureusement à la première. L'-d
option définit le délimiteur comme une virgule plutôt qu'un onglet.Sinon, faire
PS Oui, on peut simplifier ce qui précède pour
ou
qui a l'avantage de ne pas utiliser
cat
.Cependant, je n'ai pas utilisé cet idiome exprès , pour des raisons de clarté - il est moins bavard et j'aime bien
cat
(CATS ARE NICE). Alors s'il vous plaît ne pas éditer.Alternativement, si vous préférez coller aux chats (coller est la commande pour concaténer des fichiers horizontalement, tandis que cat les concaténer verticalement), vous pouvez utiliser:
la source
paste
commande fonctionne parfaitement, pouvez-vous s'il vous plaît donner un peu plus d'explications à ce sujet. Les traits d'union ???cat
argument. Nesed "N;s/\n/,/" file.in > file.out
fonctionne pas?Si quelqu'un qui atterrit ici cherche à combiner toutes les lignes dans un liner CSV, essayez
la source
Avec sed, joignez (N) toutes les 2 lignes et remplacez la nouvelle ligne (\ n) par ",".
la source
Notez également que, comme nous remplaçons simplement un caractère par un autre (chaque nouvelle ligne par une virgule), nous pouvons travailler sur le fichier d'entrée à la place:
(mais attention, il est possible que cela ne fonctionne pas sur des systèmes non-Unix dotés de terminateurs CRLF (comme ceux de Microsoft) que certains POSIX émulés
paste
pourraient traiter de manière non-Unix)la source
1
fait ici1<>
? est-ce une faute de frappe?Voici un one-liner (bien que potentiellement des millions de commandes) utilisant Bash pur:
J'utilise un sous-shell (la parenthèse) pour ne pas avoir à stocker ni restaurer
IFS
. Ce que l’autre devrait faire pour ne pas gâcher l’environnement des utilisateurs au cas où la source serait source L'alternative serait de passer que les nouvelles IFS uniquementread
commeIFS= read -r name
,IFS= read -r code
.Le fait que toutes les commandes de la boucle soient intégrées au shell rend ses performances acceptables et est même plus rapide que les autres solutions pour les petits fichiers. Mais beaucoup de gens considéreraient cela comme une mauvaise pratique et il faut être prudent lorsqu’on la généralise à autre chose.
la source
while IFS='\n' read -r name; do IFS='\n' read -r code ... done < file.in
, ce qui est un idiome que je vois souvent dans les scripts shell. Le-r
drapeauread
signifie "interprète le caractère '\' suivi du caractère 'n' dans le flux stdin comme deux caractères plutôt que comme une nouvelle ligne." On peut soutenir qu'il peut être plus esthétique de créer le sous-shell que de le répéterIFS='\n'
.-r
amélioré techniquement la solution. Génial! Je ne suis pas fan de l'idée de passer unIFS
double changé . Si j'avais utilisé une lecture, super sympa, mais pas deux fois. Bien sûr, c'est une question d' opinion . L'utilisation d'un sous-shell est un peu plus complexe que la connaissance générale de Bash, de sorte que beaucoup de gens auront du mal à comprendre son objectif. C'est une mauvaise chose.Pour l’ensemble complet de réponses, une
awk
solution possible pourrait être:la source
printf
? Echouera dans les rares cas où un nom de station contient un spécificateur de format. (Voir pastebin.com/wgxFttrJ pour un exemple.) Mais ceci est juste une supposition, le vote par opposition ne vient pas de moi.Hoary vieux marron d'un
awk
idiomela source
awk '{ORS=NR%2?",":"\n"};1'
est plus court et plus idiomeprint
et l’intention est claire.1
C’est tout aussi clair pour les anciensawk
comme moi mais je préfèreprint
sed
pendant un moment avant de chercher, mais je pouvaisawk
combiner toutes les 4 lignes plus facilement. M'a sauvé un voyage à la$EDITOR
!Possible aussi avec perl,
perl -pe 's/^\d+\.\s+//;$.&1?chomp:print","' file
la source
Par exemple:
Sortie: (note:
xargs -L number_of_columns
fonctionne bien avec la plupart des colonnes et pas seulement toutes les deux lignes)la source
Solution POSIX avec
pr
:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html
la source