Enumerate tuples in bash?

Can tuples be encoded in bash?

As an example, it would be great if the following work:

for (i,j) in ((c,3), (e,5)); do echo "$i and $j"; done 

Is there a workaround that somehow allows me to iterate over tuples?

+45
bash for-loop
Mar 15 '12 at 2:16
source share
6 answers
 $ for i in c,3 e,5; do IFS=","; set -- $i; echo $1 and $2; done c and 3 e and 5 

About this use of set (from man builtins ):

Any arguments remaining after processing the options are considered as values ​​for the positional parameters and are assigned in the order equal to $ 1, $ 2, ... $ n

IFS="," sets the field separator so that each $i correctly segmented into $1 and $2 .

Through this blog .

Edit: a more correct version, as suggested by @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 
+54
Mar 15 '12 at 2:21
source share
β€” -

I believe this solution is a little cleaner than the others that were sent, h / t in this bash style to illustrate how read can be used to split lines on a delimiter and assign them to separate variables.

 for i in c,3 e,5; do IFS=',' read item1 item2 <<< "${i}" echo "${item1}" and "${item2}" done 
+8
Apr 04 '16 at 3:08 on
source share
 c=('a' 'c') n=(3 4 ) for i in $(seq 0 $((${#c[*]}-1))) do echo ${c[i]} ${n[i]} done 

Sometimes it’s more convenient.

To explain the ugly part, as noted in the comments:

seq 0 2 creates a sequence of numbers 0 1 2. $ (cmd) is command substitution, therefore, for this example, seq 0 2 is displayed, which is a numerical sequence. But what is the upper bound, $((${#c[*]}-1)) ?

$ ((somthing)) is an arithmetic extension, so $ ((3 + 4)) is 7, etc. Our expression ${#c[*]}-1 , so something is 1. It's pretty simple if we know what ${#c[*]} .

c is an array, c [*] is just an array, $ {# c [*]} is the size of the array, which in our case is 2. Now we discard everything: 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 . Since the last element in the array has an index, which is the length of the array - 1.

+6
Mar 15 '12 at 11:22
source share
 $ echo 'c,3;e,5;' | while IFS=',' read -d';' ij; do echo "$i and $j"; done c and 3 e and 5 
+4
Mar 15 2018-12-12T00:
source share

Using GNU Parallel:

 parallel echo {1} and {2} ::: ce :::+ 3 5 

Or:

 parallel -N2 echo {1} and {2} ::: c 3 e 5 

Or:

 parallel --colsep , echo {1} and {2} ::: c,3 e,5 
+1
Nov 05 '16 at 8:49
source share

A bit more, but may be useful:

 a='((c,3), (e,5))' IFS='()'; for t in $a; do [ -n "$t" ] && { IFS=','; set -- $t; [ -n "$1" ] && echo i=$1 j=$2; }; done 
0
Mar 15 '12 at 2:29
source share



All Articles