J'essaie de convertir un fichier texte en une feuille de calcul séparée par des tabulations. Mon fichier texte ressemble à ceci:
Dog
Cat
Fish
Lizard
Wolf
Lion
Shark
Gecko
Coyote
Puma
Eel
Iguana
Avec les fonctions standard de recherche et de remplacement dans Gedit ou LibreOffice, il est facile de remplacer la fin de ligne par un onglet. Mais si j'échange simplement les retours chariot pour les onglets, j'obtiendra ceci:
Dog Cat Fish Lizard Wolf Lion Shark Gecko Coyote Puma Eel Iguana
Mais ce que je dois faire, c'est que cela ressemble à ceci:
Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana
Alors, puis-je échanger chaque caractère de fin de ligne pour un onglet sauf pour chaque quatrième ligne?
Je ne sais pas si ce genre d'itération conditionnelle peut être fait avec des expressions régulières dans un programme comme Gedit ou LibreOffice, alors peut-être que cela doit être une sorte de fonction de ligne de commande? Je ne sais même pas quel est le meilleur outil pour commencer.
Mise à jour:
J'ai essayé les commandes suivantes:
sed 'N;N;N;s/\n/\t/g' file > file.tsv
paste - - - - < file > file.tsv
pr -aT -s$'\t' -4 file > file.tsv
xargs -d '\n' -n4 < inputfile.txt
Mais lorsque j'essaie d'ouvrir le fichier tsv
résultant dans LibreOffice, les colonnes ne sont pas tout à fait correctes. Je ne sais pas si cela signifie que je n'exécute pas correctement les commandes ci-dessus, ou si je fais quelque chose de mal dans la fonction d'importation de LibreOffice:
Juste pour référence, le résultat souhaité devrait ressembler à ceci:
Vous pouvez utiliser un éditeur de ligne de commande tel que sed
sed 'N;N;N;s/\n/\t/g' file > file.tsv
ou, plus par programme, en ajoutant des barres obliques inversées à chacune des lignes à joindre à l'aide de l'opérateur d'adresse n skip m
de GNU sed et le suivre avec le classique one-liner pour joindre des lignes continues:
sed '0~4! s/$/\t\\/' file | sed -e :a -e '/\\$/N; s/\\\n//; ta'
Voir par exemple Sed One-Liners Explained :
Ajoute une ligne à la suivante si elle se termine par une barre oblique inversée "\".
sed -e :a -e '/\\$/N; s/\\\n//; ta'
Cependant, à mon humble avis, l’un des autres utilitaires de traitement de texte standard, par exemple.
paste - - - - < file > file.tsv
(le nombre de -
correspondra au nombre de colonnes) ou
pr -aT -s$'\t' -4 file > file.tsv
(Vous pouvez omettre le -s$'\t
si la sortie ne doit pas être séparée par plusieurs onglets).
Le comportement étrange de réimportation que vous observez est presque certainement dû au fait que le fichier d'origine comporte des fins de ligne CRLF de style Windows. Si vous devez utiliser des fichiers de Windows, vous pouvez intégrer la conversion à la commande de différentes manières, par exemple.
tr -d '\r' < file.csv | paste - - - -
ou
sed 'N;N;N;s/\r\n/\t/g' file.csv
Le premier supprimera TOUS les retours à la ligne, tandis que le dernier conservera un CR à la fin de chacune des nouvelles lignes (ce qui peut être ce que vous voulez si l'utilisateur final visé est Windows).
Vous pouvez utiliser xargs
pour toujours regrouper quatre lignes en une, séparées par un seul espace chacune:
xargs -d '\n' -n4 < inputfile.txt
-d '\n'
définit le délimiteur d'entrée sur un caractère de nouvelle ligne, sinon il se briserait également sur les espaces. Si vous n'avez de toute façon qu'un seul mot par ligne de saisie, vous pouvez même l'omettre.-n4
définit le nombre d'arguments (le nombre d'éléments d'entrée par ligne de sortie) sur 4.
Sortie:
Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana
Ou si vous voulez des tabulations comme séparateurs au lieu d'espaces, vous pouvez les remplacer par la suite. Toutefois, si vous avez des espaces dans vos lignes d’entrée, celles-ci seront également remplacées:
xargs -d '\n' -n4 | tr ' ' '\t'
Sortie (en fonction de la largeur de l'onglet du navigateur/terminal):
Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana
Vous pouvez aussi utiliser:
awk -v ORS="" '{print $1; print NR%4==0?"\n":"\t"}' file > file.tsv
Les deux variables intégrées awk sont:
ORS
: O utput R ecord S eparator (default = newline). Il est ajouté à la fin de chaque commande d'impression.NR
: N nombre total de personnes R ow awk est en cours de traitement.Cette commande affichera, pour chaque ligne, le contenu de la première colonne (et ici uniquement). Ensuite, il choisit d’ajouter une nouvelle ligne ou un onglet en testant le reste de la division de NR
par 4.
Une autre approche la plus courte awk
:
awk '{printf $0 (NR%4?"\t":"\n")}' infile
Ceci printf est la seule colonne suivie de next, next et ... et d'un caractère de tabulation \t
après chaque mais printf un caractère \n
ewline when N nombre entier de R ecord était un facteur de 4 (où NR%4
retournera 0 (false), ce que fait l'opérateur ternaire condition(s)?when-true:when-false
.)
Ma solution à cela serait d'utiliser la combinaison de sed
et sed
name__. Tout d'abord, vous pouvez marquer chaque ligne avec un caractère spécial, par exemple >
, en utilisant cette solution:
Dans ce cas, vous voulez commencer à la ligne 5 et marquer toutes les 4 lignes après celle-ci. Dans GNU sed
qui peut être donné sous la forme d'une adresse 5~4
. Vous pouvez utiliser cette commande:
sed '5~4s/^/>/' file1 > file2
Ensuite, vous devez supprimer les nouvelles lignes, ce qui peut être fait avec une boucle sed
name__:
sed ':a;N;s/\n/ /;ba' file2 > file3
Il existe des moyens plus simples de convertir les nouvelles lignes en un autre caractère, par exemple avec tr
name__:
tr '\n' ' ' < file2 > file3
De toute façon, la combinaison des deux donne
Dog Cat Fish Lizard >Wolf Lion Shark Gecko >Coyote Puma Eel Iguana
(la version sed
laisse une nouvelle ligne de fin, contrairement à la version tr
name__)
Après cela, il vous suffit de convertir les caractères spéciaux que vous avez insérés en nouvelles lignes; voir par exemple Convertit un fichier délimité par des tabulations pour utiliser des nouvelles lignes . Dans ce cas, remplacez >
par des nouvelles lignes:
sed 'y/>/\n/' file3 > outfile
La commande y
remplit la même fonction que tr
name__, transformant un caractère en un autre, mais vous pouvez également utiliser la commande s
name__. Avec s
name__, vous avez besoin de g
pour traiter chaque correspondance de la ligne (sed 's/>/\n/g'
).
Plutôt que de créer deux fichiers intermédiaires, vous pouvez utiliser des pipes:
$ sed '5~4s/^/>/' file | sed ':a;N;s/\n/ /;ba' | sed 'y/>/\n/'
Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana
Si les espaces de fin sont un problème, vous pouvez ajouter une autre commande pour les supprimer:
| sed 's/ $//'
Par souci de "complétude" voici une solution pure bash:
#!/usr/bin/env bash
sep=$'\t'
while read one \
&& read two \
&& read three \
&& read four
do
printf "%s\n" "$one$sep$two$sep$three$sep$four"
done
Fonctionne également avec des espaces, en supposant que IFS
est correctement défini (ce qui devrait par défaut être AFAIK). De plus, je pense que cela pourrait même être un script shell portable et fonctionner avec n’importe quel shell compatible POSIX.
Une macro vim (enregistrée avec q) peut appliquer votre opération, puis sauter trois lignes. Ensuite, vous exécutez cette macro n fois.
par exemple:
qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q
Puisque vous avez demandé une solution Gedit, cela devrait fonctionner:
Trouver:
(\w+)[\r\n]+(\w+)[\r\n]+(\w+)[\r\n]+(\w+)[\r\n]+
Remplacer par:
\1\t\2\t\3\t\4\n
Assurez-vous que la case à cocher pour les expressions régulières est cochée.
Comment ça marche:
La première étape consiste à rechercher une série de caractères Word, avec\w +, et à capturer les résultats dans la variable\1 en encapsulant des parenthèses autour de l'expression:
(\w+)
Ensuite, nous recherchons une série de caractères de fin de ligne,\r et\n, ou CR et LF. Comme les fichiers au format Windows utilisent les deux, nous créons une classe de caractères en les enveloppant entre crochets. Le plus le fait rechercher un ou plusieurs caractères:
[\r\n]+
Enfin, nous répétons ceci 3 fois de plus, en stockant chaque mot suivant dans les variables\2,\3 et\4. Cela rend notre remplacement avec une expression simple. Nous avons juste besoin de placer les caractères de tabulation,\t, et un nouveau caractère de ligne,\n, aux emplacements appropriés pour la mise en forme dont vous avez besoin.