Question Commande Linux / Unix pour joindre N lignes d'entrée avec des délimiteurs?


Sur la ligne de commande Linux / Unix, je souhaite activer ceci:

A
B
C
A
B
C
.
.
.

dans ceci:

A,B,C
A,B,C
...

Existe-t-il une commande intégrée simple pour ce faire ou est-ce que cela nécessite de plonger dans Awk, Perl, etc.?


4
2018-03-29 16:39


origine




Réponses:


Ne sais pas un tel intégré. En utilisant Bash vous pouvez:

while read a && read b && read c ; do echo $a,$b,$c ; done < file

7
2018-03-29 16:48



Si vous n'avez que 5 lignes, vous ne voudrez peut-être pas perdre les lignes 4 et 5 simplement parce que vous n'avez pas la ligne 6. - musiphil


C'est horrible, sûrement quelque chose comme

tr \\n ' '

ferait la même chose?

Donc, par exemple joindre les lignes du fichier file_lines utilisation

cat file_lines | tr \\n ' '

4
2018-02-17 09:55



Il ne voulait pas tout sur une seule ligne, semble-t-il. - l0b0
Exactement. En référence à l'énoncé du problème, cela produirait une seule ligne avec tout ce qui s'y trouve (A B C A B C A B C A B C A B C ...) ce qui n'est pas ce qui a été demandé. - Alan Krueger


Si vous avez la chance de ne pas avoir d'espace dans l'entrée, alors

xargs -n3 echo |tr ' ' ,

le ferait.


2
2017-08-20 00:44



C'est un bon que j'allais suggérer. Très élégant. Si vous avez des espaces, utilisez xargs -l3 - xpt
le tr va modifier la sortie s'il y a des espaces dans l'entrée, même avec xargs -l - Steven Taschuk
Bon alors, je vais donner ma propre réponse. - xpt


Solution POSIX avec pr:

pr -3 -a -t -s, file

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html


1
2018-05-19 02:19





Voici une solution en python:

#!/usr/bin/python3

def njoin(filename, outfn="", n=3, linesuffix=" "):
    if not outfn:
        outfn = filename + ".join"
    with open(filename) as infh, open(outfn, "w") as outfh:
        nline = 0
        for line in infh:
            if nline % n != n-1:
                line = line.rstrip() + linesuffix
            outfh.write(line)
            nline += 1

Dans votre cas, vous pouvez utiliser la fonction comme ceci:

njoin("/path/to/file", n=3, linesuffixe=",")

0
2018-06-14 20:23





L’échantillon que vous avez donné comporte 3 lignes mais votre sujet met l’accent sur N lignes d'entrée, donc je suppose que 3 lignes est uniquement à des fins d'illustration, et ce dont vous avez vraiment besoin est que N lignes d'entrée, qui pourraient dépasser 10, ce qui rend le script bash accepté impossible à gérer.

Il existe des commandes intégrées simples pour faire cela, sans plonger dans Awk ou Perl. Voici un moyen.

Tout d'abord, l'entrée de l'échantillon,

 $ seq 12 | cat -n 
     1  1
     2  2
     3  3
     4  4
     5  5
     6  6
     7  7
     8  8
     9  9
    10  10
    11  11
    12  12

Maintenant supposons N=4:

N=4
$ seq 12 | cat -n | sed 's/$/,/' | xargs -l$N | sed 's/,$//'
1 1, 2 2, 3 3, 4 4
5 5, 6 6, 7 7, 8 8
9 9, 10 10, 11 11, 12 12

Je crois que cela devrait être proche de ce que vous recherchez.


0
2017-08-20 01:35





La commande GNU / Linux pour fusionner chaque groupe de N lignes en une seule ligne est un paste commander. Ce n'est pas une commande intégrée, mais elle fait partie de coreutils, elle est donc installée par défaut.

Votre exemple ressemblera à ceci:

user@host:~$ cat ABC.text
A
B
C
A
B
C

user@host:~$ cat ABC.text | paste - - - -d,
A,B,C
A,B,C

S'il y a juste 5 lignes d'entrée, la dernière ligne de sortie sera incomplète:

user@host:~$ cat ABC.text | head -5 | paste - - - -d,
A,B,C
A,B,

Si on veut grouper les lignes pas par 3 mais par 2:

user@host:~$ cat ABC.text | paste - - -d,
A,B
C,A
B,C

S'il y a juste 5 lignes d'entrée, la dernière ligne de sortie sera incomplète:

user@host:~$ cat ABC.text | head -5 | paste - - -d,
A,B
C,A
B,

Comme vous pouvez le voir, vous mettez autant - (qui dans ce cas fait référence à stdin), en nombre de lignes que vous souhaitez fusionner en un seul. Si le nombre de lignes en entrée est insuffisant, la dernière ligne commune sera incomplète.

Pour gérer un plus grand nombre de lignes dans un groupe, il vous suffit d’ajouter -.

Voir man paste pour plus d'informations.


Regardons un exemple réel: sortie de iwlist commander. Tout d'abord, choisissons seulement ESSID lignes de la sortie (et ajoutons un peu de brouillage, cette partie ne changera pas, donc il peut être ignoré):

user@host:~$ iwlist wifi scanning | grep "ESSID" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/\1XX:XX:XX:XX\3/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/\1\2......\"/g" 
ESSID:"DIREC......"
ESSID:"MGTS_......"
ESSID:"the g......"
ESSID:"MGTS_......"
ESSID:"sunny......"
ESSID:"beeli......"
ESSID:"Beeli......"
ESSID:"HG530......"
ESSID:"MGTS_......"
ESSID:"Home_......"

Si plus tard nous voulons ajouter adresses à notre sortie, alors la sortie se transformera en lignes en alternance avec adresses et ESSID.

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/\1XX:XX:XX:XX\3/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/\1\2......\"/g"
Cell 01 - Address: 12:XX:XX:XX:XX:7A
ESSID:"DIREC......"
Cell 02 - Address: 70:XX:XX:XX:XX:32
ESSID:"MGTS_......"
Cell 03 - Address: E0:XX:XX:XX:XX:73
ESSID:"the g......"
Cell 04 - Address: 44:XX:XX:XX:XX:D2
ESSID:"MGTS_......"
Cell 05 - Address: 00:XX:XX:XX:XX:54
ESSID:"sunny......"
Cell 06 - Address: 00:XX:XX:XX:XX:7C
ESSID:"beeli......"
Cell 07 - Address: EC:XX:XX:XX:XX:DC
ESSID:"Beeli......"
Cell 08 - Address: C8:XX:XX:XX:XX:9F
ESSID:"HG530......"
Cell 09 - Address: CC:XX:XX:XX:XX:02
ESSID:"MGTS_......"
Cell 10 - Address: 28:XX:XX:XX:XX:E8
ESSID:"Home_......"

Pour fusionner toutes les deux lignes en une seule, ajoutez | paste - -:

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/\1XX:XX:XX:XX\3/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/\1\2......\"/g" | paste - -
Cell 01 - Address: 12:XX:XX:XX:XX:7A    ESSID:"DIREC......"
Cell 02 - Address: 70:XX:XX:XX:XX:32    ESSID:"MGTS_......"
Cell 03 - Address: E0:XX:XX:XX:XX:73    ESSID:"the g......"
Cell 04 - Address: 44:XX:XX:XX:XX:D2    ESSID:"MGTS_......"
Cell 05 - Address: 00:XX:XX:XX:XX:54    ESSID:"sunny......"
Cell 06 - Address: 00:XX:XX:XX:XX:7C    ESSID:"beeli......"
Cell 07 - Address: EC:XX:XX:XX:XX:DC    ESSID:"Beeli......"
Cell 08 - Address: C8:XX:XX:XX:XX:9F    ESSID:"HG530......"
Cell 09 - Address: CC:XX:XX:XX:XX:02    ESSID:"MGTS_......"
Cell 10 - Address: 28:XX:XX:XX:XX:E8    ESSID:"Home_......"

Si plus tard nous voulons ajouter un Protocole, Les débits binaires et La fréquence, alors la sortie sera une liste de groupes de 5 lignes eash (adresse, ESSID, Protocole, La fréquence, et Taux de bits).

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID\|Protocol\|Rates\|Frequency" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/\1XX:XX:XX:XX\3/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/\1\2......\"/g"
Cell 01 - Address: 12:XX:XX:XX:XX:7A
ESSID:"DIREC......"
Protocol:IEEE 802.11gn
Frequency:2.412 GHz (Channel 1)
Bit Rates:144 Mb/s
Cell 02 - Address: 70:XX:XX:XX:XX:32
ESSID:"MGTS_......"
Protocol:IEEE 802.11bgn
Frequency:2.412 GHz (Channel 1)
Bit Rates:130 Mb/s
Cell 03 - Address: E0:XX:XX:XX:XX:73
ESSID:"the g......"
Protocol:IEEE 802.11bg
Frequency:2.412 GHz (Channel 1)
Bit Rates:54 Mb/s
Cell 04 - Address: 44:XX:XX:XX:XX:D2
ESSID:"MGTS_......"
Protocol:IEEE 802.11bgn
Frequency:2.412 GHz (Channel 1)
Bit Rates:130 Mb/s
Cell 05 - Address: 00:XX:XX:XX:XX:54
ESSID:"sunny......"
Protocol:IEEE 802.11bg
Frequency:2.427 GHz (Channel 4)
Bit Rates:54 Mb/s
Cell 06 - Address: 00:XX:XX:XX:XX:7C
ESSID:"beeli......"
Protocol:IEEE 802.11bgn
Frequency:2.422 GHz (Channel 3)
Bit Rates:300 Mb/s
Cell 07 - Address: EC:XX:XX:XX:XX:DC
ESSID:"Beeli......"
Protocol:IEEE 802.11bgn
Frequency:2.437 GHz (Channel 6)
Bit Rates:108 Mb/s
Cell 08 - Address: C8:XX:XX:XX:XX:9F
ESSID:"HG530......"
Protocol:IEEE 802.11bgn
Frequency:2.447 GHz (Channel 8)
Bit Rates:108 Mb/s
Cell 09 - Address: CC:XX:XX:XX:XX:02
ESSID:"MGTS_......"
Protocol:IEEE 802.11bgn
Frequency:2.442 GHz (Channel 7)
Bit Rates:130 Mb/s
Cell 10 - Address: 28:XX:XX:XX:XX:E8
ESSID:"Home_......"
Protocol:IEEE 802.11bgn
Frequency:2.472 GHz (Channel 13)
Bit Rates:108 Mb/s

Pour fusionner toutes les 5 lignes en une seule, ajoutez simplement | paste - - - - -.

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID\|Protocol\|Rates\|Frequency" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/\1XX:XX:XX:XX\3/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/\1\2......\"/g" | paste - - - - - 
Cell 01 - Address: 12:XX:XX:XX:XX:7A    ESSID:"DIREC......" Protocol:IEEE 802.11gn  Frequency:2.412 GHz (Channel 1) Bit Rates:144 Mb/s
Cell 02 - Address: 70:XX:XX:XX:XX:32    ESSID:"MGTS_......" Protocol:IEEE 802.11bgn Frequency:2.412 GHz (Channel 1) Bit Rates:130 Mb/s
Cell 03 - Address: E0:XX:XX:XX:XX:73    ESSID:"the g......" Protocol:IEEE 802.11bg  Frequency:2.412 GHz (Channel 1) Bit Rates:54 Mb/s
Cell 04 - Address: 44:XX:XX:XX:XX:D2    ESSID:"MGTS_......" Protocol:IEEE 802.11bgn Frequency:2.412 GHz (Channel 1) Bit Rates:130 Mb/s
Cell 05 - Address: 00:XX:XX:XX:XX:54    ESSID:"sunny......" Protocol:IEEE 802.11bg  Frequency:2.427 GHz (Channel 4) Bit Rates:54 Mb/s
Cell 06 - Address: 00:XX:XX:XX:XX:7C    ESSID:"beeli......" Protocol:IEEE 802.11bgn Frequency:2.422 GHz (Channel 3) Bit Rates:300 Mb/s
Cell 07 - Address: EC:XX:XX:XX:XX:DC    ESSID:"Beeli......" Protocol:IEEE 802.11bgn Frequency:2.437 GHz (Channel 6) Bit Rates:108 Mb/s
Cell 08 - Address: C8:XX:XX:XX:XX:9F    ESSID:"HG530......" Protocol:IEEE 802.11bgn Frequency:2.447 GHz (Channel 8) Bit Rates:108 Mb/s
Cell 09 - Address: CC:XX:XX:XX:XX:02    ESSID:"MGTS_......" Protocol:IEEE 802.11bgn Frequency:2.442 GHz (Channel 7) Bit Rates:130 Mb/s
Cell 10 - Address: 28:XX:XX:XX:XX:E8    ESSID:"Home_......" Protocol:IEEE 802.11bgn Frequency:2.472 GHz (Channel 13)    Bit Rates:108 Mb/s

EOT


0
2018-02-15 23:14