J'ai un fichier texte au format suivant. La première ligne est la «CLÉ» et la deuxième ligne est la «VALEUR».
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
J'ai besoin de la valeur dans la même ligne que celle de la clé. La sortie devrait donc ressembler à ceci ...
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1
Ce sera mieux si je pouvais utiliser un délimiteur comme $
ou ,
:
KEY 4048:1736 string , 3
Comment fusionner deux lignes en une seule?
pr
,paste
,awk
,xargs
,sed
etpure bash
! (xargs
est le plus lent, le plus lent que bash !)Réponses:
awk:
Remarque, il y a une ligne vide à la fin de la sortie.
sed:
la source
printf
des chaînes d'expansion comme%s
sont trouvées à l'intérieur$0
. Cet échec peut être évité comme ceci:'NR%2{printf "%s ",$0;next;}1'
1
signe après l'accolade de fermeture?paste
est bon pour ce travail:la source
paste
, d'autre part, se comporte parfaitement. +1.cut
mais j'oublie toujourspaste
. Il rock pour ce problème. J'avais besoin de combiner toutes les lignes de stdin et je l'ai fait facilement avecpaste -sd ' ' -
.-
signifie stdin, doncpaste - -
signifie lire à partir de stdin, puis lire à partir de stdin, vous pouvez en empiler autant que vous le souhaitez.Alternative à sed, awk, grep:
Ceci est préférable lorsque vous souhaitez joindre N lignes et que vous n'avez besoin que d'une sortie délimitée par des espaces.
Ma réponse originale était celle
xargs -n2
qui sépare les mots plutôt que les lignes.-d
peut être utilisé pour diviser l'entrée par n'importe quel caractère unique.la source
-d '\n'
xargs
utilisateur régulier mais je ne le savais pas. Bon conseil.Il y a plus de façons de tuer un chien que de le suspendre. [1]
Mettez le délimiteur de votre choix entre les guillemets.
Références:
la source
$0
. Lagetline
commande saisit également "la prochaine" ligne d'entrée et la place dans$0
. Ainsi, la première instruction saisit la première ligne et la commande d'impression concatène ce qui a été sauvegardé dans la variablekey
avec une chaîne contenant une virgule, ainsi que la ligne qui a été récupérée à l'aide degetline
. Plus clair? :)Voici ma solution en bash:
la source
Bien qu'il semble que les solutions précédentes fonctionnent, si une seule anomalie se produit dans le document, la sortie se décompose. Ci-dessous est un peu plus sûr.
la source
/KEY/
-on? Que fait lep
à la fin?/KEY/
recherche de la ligne avec leKEY
. lep
imprime le résultat. c'est plus sûr car il n'applique l'opération que sur les lignes contenant unKEY
.Voici une autre façon avec
awk
:Comme indiqué par Ed Morton dans les commentaires, il est préférable d'ajouter des accolades pour la sécurité et des parens pour la portabilité.
ORS
signifie Output Record Separator. Ce que nous faisons ici, c'est tester une condition en utilisant leNR
qui stocke le numéro de ligne. Si le modulo deNR
est une valeur vraie (> 0), nous définissons le séparateur de champ de sortie sur la valeur deFS
(séparateur de champ) qui par défaut est un espace, sinon nous attribuons la valeur deRS
(séparateur d'enregistrement) qui est une nouvelle ligne.Si vous souhaitez ajouter
,
comme séparateur, utilisez ce qui suit:la source
ORS
et cela est traité comme étanttrue
donné que ORS obtient une valeur qui n'est pas zéro ou une chaîne nulle et qui devine correctement que cela devrait être une piqûre au lieu d'une comparaison numérique? Est-ce autre chose? Je ne suis vraiment pas sûr et je l'aurais donc écrit commeawk '{ORS=(NR%2?FS:RS)}1' file
. J'ai mis entre parenthèses l'expression ternaire pour assurer la portabilité également."ex" est un éditeur de ligne scriptable qui appartient à la même famille que sed, awk, grep, etc. Je pense que c'est peut-être ce que vous recherchez. De nombreux clones / successeurs vi modernes ont également un mode vi.
Cela dit , pour chaque ligne, si elle correspond à « KEY » effectuer un j oin de la ligne suivante. Une fois cette commande terminée (sur toutes les lignes), lancez un w rite et q uit.
la source
Si Perl est une option, vous pouvez essayer:
la source
-0
perl dit de définir le séparateur d'enregistrement ($/)
à null, afin que nous puissions étendre plusieurs lignes dans notre modèle de correspondance. Les pages de manuel sont un peu trop techniques pour que je puisse comprendre ce que cela signifie en pratique.Vous pouvez utiliser awk comme ceci pour combiner deux paires de lignes:
la source
Une autre solution utilisant vim (juste pour référence).
Solution 1 :
Ouvrez le fichier dans vim
vim filename
, puis exécutez la commande:% normal Jj
Cette commande est très simple à comprendre:
Après cela, enregistrez le fichier et quittez avec
:wq
Solution 2 :
Exécutez la commande dans le shell,
vim -c ":% normal Jj" filename
puis enregistrez le fichier et quittez avec:wq
.la source
norm!
plus robuste qu'ennormal
cas deJ
remappage. +1 pour la solution vim.Vous pouvez également utiliser la commande vi suivante:
la source
:%g//j
puisque tout ce dont vous avez besoin est une correspondance pour que la jointure soit exécutée, et une chaîne nulle est toujours une expression régulière valide.//
, le modèle de recherche précédent sera utilisé à la place. S'il n'y a pas de modèle précédent, Vim signale simplement une erreur et ne fait rien. La solution de Jdamian fonctionne tout le temps.Une légère variation de la réponse de Glenn Jackman en utilisant
paste
: si la valeur de l'-d
option délimiteur contient plus d'un caractère, faitpaste
défiler les caractères un par un et combiné avec les-s
options continue de le faire tout en traitant le même fichier d'entrée.Cela signifie que nous pouvons utiliser tout ce que nous voulons comme séparateur plus la séquence d'échappement
\n
pour fusionner deux lignes à la fois.En utilisant une virgule:
et le signe dollar:
Ce que cela ne peut pas faire, c'est utiliser un séparateur composé de plusieurs caractères.
En prime, si le
paste
est compatible POSIX, cela ne modifiera pas la nouvelle ligne de la dernière ligne du fichier, donc pour un fichier d'entrée avec un nombre impair de lignes commepaste
ne clouera pas sur le caractère de séparation sur la dernière ligne:la source
Cela se lit comme
la source
Dans le cas où je devais combiner deux lignes (pour un traitement plus facile), mais laisser les données au-delà du spécifique, j'ai trouvé cela utile
data.txt
la sortie ressemble alors à:
converti_data.txt
la source
Une autre approche utilisant vim serait:
Cela applique un
join
(à la ligne en dessous) à toutes les lignes qui contiennent le motKEY
. Résultat:la source
Le moyen le plus simple est ici:
la source
-0
engloutit le fichier entier au lieu de le lire ligne par ligne;pE
encapsule le code avec une boucle et imprime la sortie, voir les détails dans http://perldoc.perl.org/perlrun.html ;^KEY
correspond à "KEY" au début de la ligne, suivi d'une correspondance non gourmande de tout (.*?
) avant la séquence de\s+
de toute nature, y compris les sauts de ligne;(\d+)
que nous capturons et réinsérons plus tard comme$1
;suivi de la fin de la ligne
$
.\K
exclut commodément tout ce qui se trouve sur son côté gauche de la substitution, donc{ $1}
remplace seulement 1-2 séquence, voir http://perldoc.perl.org/perlre.html .la source
Une solution plus générale (permet de joindre plus d'une ligne de suivi) sous forme de script shell. Cela ajoute une ligne entre chacun, car j'avais besoin de visibilité, mais cela est facilement corrigé. Cet exemple est l'endroit où la ligne «clé» s'est terminée par: et aucune autre ligne ne l'a fait.
la source
Essayez la ligne suivante:
Mettre un délimiteur entre
par exemple, si le délimiteur est
|
, alors:la source
Vous pouvez utiliser
xargs
comme ceci:la source
xargs -n 2
mais cette réponse n'explique pas du tout cela.