2012-03-15 11 views
50

bashでタプルをループすることはできますか?以下は、働いていた場合bashでタプルをループしますか?

例として、それは素晴らしいことだ:

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

は何とか私のタプルを超えるループをすることができます回避策はありますか? (man builtinsから)setのこの使用について

+2

が、これは確かに非常に便利な質問です! –

+3

この4年後に私はまだこれを行うより良い方法がないかと思います。ああ、神様。 – Giszmo

答えて

58
$ for i in c,3 e,5; do IFS=","; set -- $i; echo $1 and $2; done 
c and 3 
e and 5 

:位置パラメータの 値と割り当てられているようにオプション処理後に残存する

任意の引数は、$ 1、$ 2に、順に処理されます ... $ nの

IFS=","セットフィールドセパレータので、すべての$iがに分割されますと$2正しく。

Via this blog。 @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 
+7

ニース - 'IFS'が保存され、コマンドラインで実行されている場合は元の値にリセットする必要があることを指摘したいだけです。また、新しい 'IFS'は、ループが実行される前に、すべての反復ではなく、一度設定することができます。 – Devourant

+1

@SLACEDIAMOND:ありがとう、私はあなたの提案を取り入れました。 –

+0

$ iがハイフンで始まる場合、 'set - $ i'より安全です。 –

0

もう少し関与しないが、有用であり得る:

a='((c,3), (e,5))' 
IFS='()'; for t in $a; do [ -n "$t" ] && { IFS=','; set -- $t; [ -n "$1" ] && echo i=$1 j=$2; }; done 
4
$ echo 'c,3;e,5;' | while IFS=',' read -d';' i j; do echo "$i and $j"; done 
c and 3 
e and 5 
6
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))

$((3 + 4))は算術展開です。私たちの式は${#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)for i in 0 1です。配列の最後の要素は配列の長さであるインデックスを持つため -

+1

あなたは 'for $ in seq 0 $(($#c [*]} - 1))))を実行する必要があります。 do [...] ' – reox

+0

@reox:完了。どうも。 –

+1

うわー、これは「私が今日見た任意のキャラクターの最も醜い束」賞を受賞しました。誰でもこの偽善が何をしているのかを説明するのに気をつけますか?私はハッシュサインで迷った... – koniiiik

10

私はこの解決策が提出された他のものより少しクリーナーだと考えています。this説明のためのbashスタイルのガイド区切り文字で文字列を分割して個々の変数に割り当てる方法

for i in c,3 e,5; do 
    IFS=',' read item1 item2 <<< "${i}" 
    echo "${item1}" and "${item2}" 
done 
1

使用GNUパラレル:

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 
+1

これは大好きですか?よく作られた*私*慣性を克服して 'gnuを並列にインストールする ' – javadba

+1

' brew install parallel' – javadba

0

使用連想配列:

declare -A pairs=(
    [c]=3 
    [e]=5 
) 
for key in "${!pairs[@]}"; do 
    value="${pairs[$key]}" 
    echo "key is $key and value is $value" 
done 

bash4.0 +用。


あなたは1日に必要ではなく、ペアの三倍も感じている場合は、より一般的なアプローチを使用することができます:pythonの背景から来る

animals=(dog cat mouse) 
declare -A sound=(
    [dog]=barks 
    [cat]=purrs 
    [mouse]=cheeps 
) 
declare -A size=(
    [dog]=big 
    [cat]=medium 
    [mouse]=small 
) 
for animal in "${animals[@]}"; do 
    echo "$animal ${sound[$animal]} and it is ${size[$animal]}" 
done 
関連する問題