Comando Linux / Unix para unir N linhas de entrada com delimitadores?

4

Na linha de comando do Linux / Unix, quero ativar isso:

A
B
C
A
B
C
.
.
.

para isso:

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

Existe um comando embutido simples para fazer isso, ou isso requer mergulhar no Awk, no Perl, etc.?

    
por Alan Krueger 29.03.2011 / 18:39

7 respostas

7

Não conheça esse tipo de built-in. Usando Bash , você pode:

while read a && read b && read c ; do echo $a,$b,$c ; done < file
    
por 29.03.2011 / 18:48
4

Isso é horrível, certamente algo como

tr \n ' '

faria o mesmo?

Assim, por exemplo para juntar linhas do arquivo file_lines use

cat file_lines | tr \n ' '
    
por 17.02.2012 / 10:55
2

Se você tiver a sorte de não ter espaços na entrada,

xargs -n3 echo |tr ' ' ,

faria isso.

    
por 20.08.2015 / 02:44
1

Solução POSIX com pr :

pr -3 -a -t -s, file

link

    
por 19.05.2018 / 04:19
0

Aqui está uma solução em 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

No seu caso, você pode usar a função assim:

njoin("/path/to/file", n=3, linesuffixe=",")
    
por 14.06.2014 / 22:23
0

A amostra que você deu tem 3 linhas, mas seu tópico enfatiza linhas N de entrada, então eu diria que 3 linhas são apenas para propósitos de ilustração, e o que você realmente precisa é que N linhas de entrada, que podem ser superiores a 10, o que, por sua vez, torna esse script bash aceito incontrolável.

Existem comandos internos simples para fazer isso, sem mergulhar no Awk ou no Perl. Aqui está um jeito.

Primeiro, a entrada de amostra,

 $ 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

Agora, suponha que 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

Eu acredito que deveria estar perto do que você está procurando.

    
por 20.08.2015 / 03:35
0

O comando GNU / Linux para mesclar cada grupo de N linhas em uma linha é um comando paste . Este não é um comando interno, mas é parte do coreutils, por isso é instalado por padrão.

Seu exemplo terá a seguinte aparência:

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

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

Se houver apenas linhas de entrada 5 , a última linha de saída ficará incompleta:

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

Se quisermos agrupar as linhas não por 3, mas por 2:

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

Se houver apenas linhas de entrada 5 , a última linha de saída ficará incompleta:

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

Como você pode ver, você está colocando quantos - (que neste caso se refere a stdin ), como o número de linhas que você deseja mesclar em um. Se o número de linhas de entrada for insuficiente, a última linha de junção estará incompleta.

Para lidar com um número maior de linhas em um grupo, você só precisa adicionar mais - .

Veja man paste para informações adicionais.

Vejamos um exemplo real: saída do comando iwlist . Primeiro, vamos escolher apenas as linhas ESSID da saída (e vamos adicionar um pouco de ofuscação; essa parte não vai mudar, então pode ser ignorada):

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

Se mais tarde quisermos adicionar endereços à nossa saída, então a saída se transformará em linhas alternadas com endereços e ESSID .

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/XX:XX:XX:XX/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/......\"/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_......"

Para mesclar todas as duas linhas em uma, adicione | paste - - :

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/XX:XX:XX:XX/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/......\"/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_......"

Se mais tarde quisermos adicionar um Protocolo , Taxas de bits e Frequência , a saída será uma lista de grupos de 5 linhas eash ( endereço , ESSID , Protocolo , Frequência e Taxas de bits ).

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID\|Protocol\|Rates\|Frequency" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/XX:XX:XX:XX/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/......\"/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

Para mesclar cada 5 linhas em uma, basta adicionar | paste - - - - - .

user@host:~$ iwlist wifi scanning | grep "Cell\|ESSID\|Protocol\|Rates\|Frequency" | sed -e 's/^ *//g' -e 's/\(ess: ...\)\(.*\)\(...$\)/XX:XX:XX:XX/g' -e "s/\(ESSID:\"\)\(.....\)\(.*\"\)/......\"/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

    
por 16.02.2017 / 00:14