4

В командной строке Linux/Unix я хочу включить это:

A
B
C
A
B
C
.
.
.

в это:

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

Есть ли простая встроенная команда, чтобы сделать это, или это требует погружения в Awk, Perl и т.д.?

7 ответов7

7

Не знаю, такой встроенный. Используя Bash вы можете:

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

Это ужасно, конечно, что-то вроде

tr \\n ' '

будет делать то же самое?

Так, например, для объединения строк файла file_lines используйте

cat file_lines | tr \\n ' '
2

Если вам повезло, что на входе нет пробелов, то

xargs -n3 echo |tr ' ' ,

сделал бы это.

1

POSIX решение с pr:

pr -3 -a -t -s, file

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

0

Вот решение в 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

В вашем случае вы можете использовать такую функцию:

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

Команда GNU/Linux для объединения каждой группы из N строк в одну строку является командой paste . Это не встроенная команда, но она является частью coreutils, поэтому она устанавливается по умолчанию.

Ваш пример будет выглядеть следующим образом:

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

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

Если есть только 5 входных строк, то последняя выходная строка будет неполной:

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

Если мы хотим сгруппировать строки не по 3, а по 2:

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

Если есть только 5 входных строк, то последняя выходная строка будет неполной:

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

Как видите, вы ставите столько - (что в данном случае относится к стандартному stdin), сколько строк вы хотите объединить в одну. Если количество входных строк недостаточно, последняя объединенная строка будет неполной.

Чтобы обработать большее количество строк в группе, вам просто нужно добавить больше - .

Смотрите man paste для дополнительной информации.


Давайте посмотрим на реальный пример: вывод команды iwlist . Во-первых, давайте выберем только строки ESSID из вывода (и давайте добавим немного запутывания; эта часть не изменится, поэтому ее можно игнорировать):

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_......"

Если позже мы захотим добавить адреса к нашему выводу, то вывод превратится в чередующиеся строки с адресами и 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_......"

Чтобы объединить каждые две строки в одну, добавьте | 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_......"

Если позже мы захотим добавить протокол, битовую скорость и частоту, то на выходе будет список групп из 5 строк (адрес, ESSID, протокол, частота и битовая скорость).

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

Чтобы объединить каждые 5 строк в одну, просто добавьте | 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

СРВ

0

Пример, который вы дали, состоит из 3 строк, но ваша тема подчеркивает N строк ввода, поэтому я предполагаю, что 3 строки предназначены только для иллюстрации, и что вам действительно нужно, так это N строк ввода, которые могут превышать 10 что, в свою очередь, делает этот принятый сценарий bash неуправляемым.

Для этого есть простые встроенные команды без погружения в Awk или Perl. Вот один из способов.

Во-первых, образец ввода,

 $ 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

Теперь предположим, что 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

Я считаю, что это должно быть близко к тому, что вы ищете.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .