web-dev-qa-db-fra.com

Est-il possible avec Gedit ou la ligne de commande de modifier chaque quatrième ligne d'un fichier texte?

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:

TSV opening in Calc

Juste pour référence, le résultat souhaité devrait ressembler à ceci:

Proper columns

11
Questioner

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 :

  1. 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).

16
steeldriver

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
13
Byte Commander

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.

3
arauk

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 \newline 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.)

3
αғsнιη

Ma solution à cela serait d'utiliser la combinaison de sedet sedname__. 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 sedqui 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 sedname__:

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 trname__:

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 sedlaisse une nouvelle ligne de fin, contrairement à la version trname__)

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 yremplit la même fonction que trname__, transformant un caractère en un autre, mais vous pouvez également utiliser la commande sname__. Avec sname__, vous avez besoin de gpour 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/ $//'
3
spaceman117X

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.

2
Daniel Jour

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
2
rackandboneman

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.

2
Jason Wood