Поведение python zip() в bash?

Существует ли аналогичная функция Python zip() в bash? Чтобы быть конкретным, я ищу эквивалентную функциональность в bash без использования python:

$ echo "A" > test_a
$ echo "B" >> test_a
$ echo "1" > test_b
$ echo "2" >> test_b
$ python -c "print '\n'.join([' '.join([a.strip(),b.strip()]) for a,b in zip(open('test_a'),open('test_b'))])"
A 1
B 2

Ответ 1

Pure bash:

[email protected]:~$ zip34() { while read word3 <&3; do read word4 <&4 ; echo $word3 $word4 ; done }
[email protected]:~$ zip34 3<a 4<b
alpha one
beta two
gamma three
delta four
epsilon five
[email protected]:~$

(старый ответ) Посмотрите join.

liori:~% cat a
alpha
beta
gamma
delta
epsilon
liori:~% cat b
one
two
three
four
five
liori:~% join =(cat -n a) =(cat -n b)
1 alpha one
2 beta two
3 gamma three
4 delta four
5 epsilon five

(предположим, что у вас есть оператор =(), как в zsh, в противном случае это более сложно).

Ответ 2

код

[tmp]$ echo "A" > test_a 
[tmp]$ echo "B" >> test_a 
[tmp]$ echo "1" > test_b
[tmp]$ echo "2" >> test_b
[tmp]$ cat test_a
A
B
[tmp]$ cat test_b
1
2
[tmp]$ paste test_a test_b > test_c
[tmp]$ cat test_c
A   1
B   2

Ответ 3

Вы можете сделать это в два этапа с cat -n, а затем join. (cat -n воспроизводит ваш файл с номерами строк в начале каждой строки. join объединяет два файла в номерах строк.)

$ echo "A" > test_a
$ echo "B" >> test_a
$ echo "X" > test_b
$ echo "Y" >> test_b
$ cat -n test_a > test_a.numbered
$ cat -n test_b > test_b.numbered
$ join -o 1.2 -o 2.2 test_a.numbered test_b.numbered
A X
B Y

Ответ 4

Вот еще один способ, используя команду paste:

$ echo A > test_a
$ echo B >> test_a
$ echo X > test_b
$ echo Y >> test_b
$ paste test_a test_b | while read a b; do echo "$a, $b"; done
A, X
B, Y

Вы можете делать всякие забавные вещи, используя подстановку процессов, например,

$ paste <(seq 1 3) <(seq 20 22) | while read a b ; do echo "$a = $b"; done
1 = 20
2 = 21
3 = 22

Будьте осторожны, поскольку, когда один из массивов длиннее, переменные могут перепутаться:

$ paste <(seq 1 3) <(seq 20 25) | while read a b ; do echo "$a = $b"; done
1 = 20
2 = 21
3 = 22
23 =
24 =
25 =

Это решение масштабируется до любого количества переменных:

$ paste <(seq 1 3) \
$     <(seq 20 22) \
$     <(echo first; echo second; echo third) \
$     <(head -n3 /etc/passwd) | while read a b c d ; do echo "$a = $b = $c = $d"; done
1 = 20 = first = root:x:0:0:root:/root:/bin/bash
2 = 21 = second = daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3 = 22 = third = bin:x:2:2:bin:/bin:/usr/sbin/nologin