J'ai deux fichiers parallèles avec le même nombre de lignes dans deux langues et je prévois de fusionner ces deux fichiers ligne par ligne avec le délimiteur |||
. Par exemple, les deux fichiers sont les suivants:
Déposer un:
1Mo 1,1 I love you.
1Mo 1,2 I like you.
Hi 1,3 I am hungry.
Hi 1,4 I am foolish.
Fichier B:
1Mo 1,1 Ich liebe dich.
1Mo 1,2 Ich mag dich.
Hi 1,3 Ich habe Durst.
Hi 1,4 Ich bin neu.
La sortie attendue est la suivante:
1Mo 1,1 I love you. ||| 1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. ||| 1Mo 1,2 Ich mag dich.
Hi 1,3 I am hungry. ||| Hi 1,3 Ich habe Durst.
Hi 1,4 I am foolish. ||| Hi 1,4 Ich bin neu.
J'ai essayé la paste
commande telle que:
paste -d "|||" fileA fileB
Mais la sortie renvoyée ne contient qu'un seul tube tel que:
1Mo 1,1 I love you. |1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. |1Mo 1,2 Ich mag dich.
Existe-t-il un moyen de séparer chaque paire de lignes par des tripes |||
?
text-processing
sed
awk
Froncer les sourcils
la source
la source
paste -d '|||' fileA - - fileB < /dev/null
Réponses:
Avec la pâte POSIX :
paste
concaténera les lignes correspondantes de tous les fichiers d'entrée. Ici, nous avons six fichiers,fileA
quatre fichiers fictifs de la norme dans-
etfileB
.La liste des délimiteurs comprend un espace, trois tuyaux et un espace dans cet ordre sera utilisé par
paste
circulairement.Pour la première ligne de six fichiers,
fileA
sera concaténé avec le premier fichier factice (qui n'est rien, grâce à la opérateur no-op :), produitline1-fileA<space>
.Le premier fichier factice sera concaténé avec le second par un tuyau, produire
line1-fileA |
, puis le deuxième fichier factice avec le troisième fichier factice, produireline1-fileA ||
, le troisième fichier factice avec le quatrième fichier factice, produireline1-fileA |||
.Et le quatrième fichier factice avec
fileB
, produireline1-fileA ||| line1-fileB
.Cette étape sera répétée pour toutes les lignes, vous donnera le résultat attendu.
L'utilisation de
:|
est pour moins de frappe, et est principalement utilisée dans le shell interactif. Dans un script, vous devez utiliser:pour empêcher la génération d'un sous-shell.
la source
:|
. alternative intelligente à</dev/null
- - - -
, mais la prochaine fois, vous pouvez même écrire quelques lignes pour expliquer :):|paste -d '|' fileA - - fileB
donne la version la plus correcte sans le délimiteur d'espace.Eh bien, cela n'utilise pas sed, awk ou grep, mais vous pouvez le faire assez facilement en bash. La commande est:
Le problème avec la pâte est que le délimiteur est un seul caractère. Vous pouvez également insérer un seul caractère et utiliser sed pour le transformer, mais cela pourrait être source d'erreurs si le caractère apparaît déjà dans le fichier d'entrée.
la source
IFS=
avant chacunread
. Vous pouvez facilement le faire avecpaste
. Voir ma réponse , et aussi celle-ci pour voir pourquoi devrait éviter d'utiliser lawhile
boucle dans le script shell.Une version awk (GNU)
Avec la
getline
commande inawk
, vous pouvez définir$0
(toutes les variables pour les colonnes) à partir du prochain enregistrement d'entrée, sigetline < "filename"
vous définissez le suivant à$0
partir du fichier spécifié.Pourquoi votre tentative n'a pas fonctionné comme prévu? De
man paste
nous pouvons liremais il utilise les délimiteurs un pour chaque colonne .
Donc, la commande
paste -d '|*|*' fileA fileB fileA fileB
me donne des lignes commeUne
sed
solution que je suggère d'éviter même si elle est proche de votre tentative d'origine, car elle corrige le comportement obtenu à votre objectif d'origine:À éviter car vous remplacez chaque modèle
|
par le nouveau|||
, mais vous devez supposer que le symbole de tuyau (|
) n'est pas présent dans vos données , sinon vous devez traiter des cas spéciaux et rendre le code plus complexe pour éviter les effets secondaires.Une variante avec la construction Here String [ 1 ]
<<<
Vous définissez 5 délimiteurs avec
-d ' ||| '
(espace, |, |, |, espace) et 4 fichiers factices (- - - -
) qui prendront les données de la chaîne vide''
.Testé sur GNU Awk 4.0.1, paste (GNU coreutils) 8.21 et sed (GNU sed) 4.2.2
la source
sed
exemple pour éviter (:-)) et plus de commentaires.Si vous voulez éviter la magie et le drame des délimiteurs circulaires et des fichiers factices, vous pouvez simplement ajouter votre délimiteur à un fichier avant de les coller:
donne
la source
vous pouvez aussi le faire en python de cette façon.
la source