Можно ли закодировать кортежи в bash?
В качестве примера было бы здорово, если бы работало следующее:
for (i,j) in ((c,3), (e,5)); do echo "$i and $j"; done
Есть ли способ обхода, который каким-то образом позволяет мне перебирать кортежи?
Можно ли закодировать кортежи в bash?
В качестве примера было бы здорово, если бы работало следующее:
for (i,j) in ((c,3), (e,5)); do echo "$i and $j"; done
Есть ли способ обхода, который каким-то образом позволяет мне перебирать кортежи?
$ for i in c,3 e,5; do IFS=","; set -- $i; echo $1 and $2; done
c and 3
e and 5
Об этом использовании set
(от man builtins
):
Любые аргументы, оставшиеся после обработки опций, рассматриваются как значения для позиционных параметров и назначаются в порядке, равном $1, $2,... $n
IFS=","
устанавливает разделитель полей таким образом, чтобы каждый $i
был правильно сегментирован на $1
и $2
.
Через этот блог.
Изменить: более правильная версия, как предложено @SLACEDIAMOND:
$ OLDIFS=$IFS; IFS=','; for i in c,3 e,5; do set -- $i; echo $1 and $2; done; IFS=$OLDIFS
c and 3
e and 5
Я считаю, что это решение немного чище, чем другие, которые были отправлены, h/t в этот bash стиль для иллюстрации как read может использоваться для разделения строк на разделителе и назначения их отдельным переменным.
for i in c,3 e,5; do
IFS=',' read item1 item2 <<< "${i}"
echo "${item1}" and "${item2}"
done
c=('a' 'c')
n=(3 4 )
for i in $(seq 0 $((${#c[*]}-1)))
do
echo ${c[i]} ${n[i]}
done
Иногда бывает удобнее.
Чтобы объяснить часть ugly
, как отмечено в комментариях:
seq 0 2 создает последовательность чисел 0 1 2. $(cmd) - подстановка команд, поэтому для этого примера выводится seq 0 2
, который является числовой последовательностью. Но какова верхняя граница, $((${#c[*]}-1))
?
$((somthing)) является арифметическим расширением, поэтому $((3 + 4)) равно 7 и т.д. Наше выражение ${#c[*]}-1
, поэтому что-то - 1. Довольно просто, если мы знаем, что такое ${#c[*]}
.
c - массив, c [*] - это всего лишь массив, ${# c [*]} - размер массива, который в нашем случае равен 2. Теперь мы отбрасываем все: for i in $(seq 0 $((${#c[*]}-1)))
for i in $(seq 0 $((2-1)))
for i in $(seq 0 1)
is for i in 0 1
. Поскольку последний элемент в массиве имеет индекс, который является длиной массива - 1.
$ echo 'c,3;e,5;' | while IFS=',' read -d';' i j; do echo "$i and $j"; done
c and 3
e and 5
Использование GNU Parallel:
parallel echo {1} and {2} ::: c e :::+ 3 5
Или:
parallel -N2 echo {1} and {2} ::: c 3 e 5
Или:
parallel --colsep , echo {1} and {2} ::: c,3 e,5
Немного больше, но может быть полезно:
a='((c,3), (e,5))'
IFS='()'; for t in $a; do [ -n "$t" ] && { IFS=','; set -- $t; [ -n "$1" ] && echo i=$1 j=$2; }; done