В командной строке Linux/Unix я хочу включить это:
A
B
C
A
B
C
.
.
.
в это:
A,B,C
A,B,C
...
Есть ли простая встроенная команда, чтобы сделать это, или это требует погружения в Awk, Perl и т.д.?
В командной строке Linux/Unix я хочу включить это:
A
B
C
A
B
C
.
.
.
в это:
A,B,C
A,B,C
...
Есть ли простая встроенная команда, чтобы сделать это, или это требует погружения в Awk, Perl и т.д.?
Не знаю, такой встроенный. Используя Bash
вы можете:
while read a && read b && read c ; do echo $a,$b,$c ; done < file
Это ужасно, конечно, что-то вроде
tr \\n ' '
будет делать то же самое?
Так, например, для объединения строк файла file_lines используйте
cat file_lines | tr \\n ' '
Если вам повезло, что на входе нет пробелов, то
xargs -n3 echo |tr ' ' ,
сделал бы это.
POSIX решение с pr
:
pr -3 -a -t -s, file
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html
Вот решение в 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=",")
Команда 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
СРВ
Пример, который вы дали, состоит из 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
Я считаю, что это должно быть близко к тому, что вы ищете.