Comment grouper les lignes d'un fichier par deux?

9

J'ai un fichier texte comme celui-ci:

a
b
c
d
e
f
g

Comment puis-je regrouper ces lignes pour obtenir une sortie comme celle-ci:

a-b
b-c
c-d
d-e
e-f
f-g

Je dois le faire en shell (sh, csh, bash).

J'ai trouvé ceci:

cat file | xargs -n2

mais le dernier élément du premier groupe n'est pas devenu le premier du second.

Costel Balta-Coman
la source

Réponses:

9

Avec awk:

awk 'NR!=1{print x"-"$0}{x=$0}' file
  • NR!=1 s'applique sur toutes les lignes, sauf la première
  • print x"-"$0 imprimer les valeurs avec un tiret entre
  • x=$0set x(pour la prochaine itération)
le chaos
la source
5

Avec POSIX sed:

sed '1{
  h
  d
}
H
x
s/\n/-/
' <file

ou version monoplace:

sed -e '1{h;d' -e\} -e 'H;x;s/\n/-/' <file
cuonglm
la source
J'ai besoin que la première lettre de la deuxième ligne soit la dernière de la première ligne ...
Costel Balta-Coman
Belle utilisation de la soute.
Wildcard
oui, ça va.
mikeserv
Pourriez-vous expliquer comment cela fonctionne?
Yossarian
5
paste -d- - ./infile <infile

^ Cela fonctionnerait très bien, sauf que votre entrée est ponctuelle. Donc...

{ echo; cat <infile; } | paste -d- - ./infile | sed '1d;$d'

... fonctionnerait, mais c'est peut-être trop compliqué ...

mikeserv
la source
Eh bien, c'est exactement la même chose qui m'est venue à l'esprit au début après avoir mal lu l'exigence OP, mais j'ai décidé de le sedfaire seul.
cuonglm
@cuonglm - l'ai-je mal lu?
mikeserv
1
Non, je parie. Mais vous devez sed 1d\;\$dle corriger.
cuonglm
Et cette variante? sed '2~2p' infile | paste -d- - -
Steeldriver
1
Maintenant, je vois. paste -d- <(head -n -1 input) <(tail -n +2 input)
Costas
2

Un de plus sed

sed '$!N;s/\n/-/p;s/-/\n/;D' <input

et peut être modifié (grâce à mikeserv ):

sed -n 'N;y/\n/-/;P;y/-/\n/;D' <input
Costas
la source
1
y/-\n/\n-/pourrait remplacer les deux s /// peut-être. Si tel était le cas, ce serait plus rapide, portable pour l'utilisation \ n et plus court.
mikeserv
1

Une version pure bash -

old=""; while read -r line ; do [[ -n "$old" ]] && echo   $old-$line;   old=$line; done  < input

a-b
b-c
c-d
d-e
e-f
f-g
jai_s
la source