在bash中循环元组?

时间:2012-03-15 02:16:28

标签: bash for-loop

是否可以在bash中循环元组?

作为一个例子,如果以下工作会很好:

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

是否有某种解决方法可以让我在元组上循环?

12 个答案:

答案 0 :(得分:71)

$ 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

通过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

答案 1 :(得分:15)

我相信这个解决方案比已经提交的其他解决方案更清晰,但不是this bash样式指南,用于说明如何使用read来在分隔符处拆分字符串并将它们分配给单个变量

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

答案 2 :(得分:7)

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.很简单,如果我们知道{{1}是的。

c是一个数组,c [*]只是整个数组,$ {#c [*]}是数组的大小,在我们的例子中是2。现在我们回滚所有内容:${#c[*]} 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。因为数组中的最后一个元素的索引是数组的长度 - 。

答案 3 :(得分:6)

$ echo 'c,3;e,5;' | while IFS=',' read -d';' i j; do echo "$i and $j"; done
c and 3
e and 5

答案 4 :(得分:6)

使用关联数组(也称为字典/ hashMap):

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

如果您觉得有一天可能需要三元而不是成对,您可以使用更一般的方法:

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

答案 5 :(得分:4)

基于@ eduardo-ivanec给出的答案,而无需设置/重置IFS,一个人可以简单地做到:

for i in "c 3" "e 5"
do
    set -- $i
    echo $1 and $2
done

输出:

c and 3
e and 5

答案 6 :(得分:2)

使用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

答案 7 :(得分:2)

在流程替代中使用printf

while read -r k v; do
    echo "Key $k has value: $v"
done < <(printf '%s\n' 'key1 val1' 'key2 val2' 'key3 val3')

Key key1 has value: val1
Key key2 has value: val2
Key key3 has value: val3

以上要求bash。如果未使用bash,则使用简单的管道:

printf '%s\n' 'key1 val1' 'key2 val2' 'key3 val3' |
while read -r k v; do echo "Key $k has value: $v"; done

答案 8 :(得分: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

答案 9 :(得分:0)

//manifest.js
module.exports = {
    server: {
        port: process.env.PORT,
        router: { stripTrailingSlash: true },
        routes: {
            files: {relativeTo: path.join(__dirname, '../client/build')},
            cors: {origin: ["*"],}
        }
    },
    register: {
        plugins: [
            { plugin: require('inert') },
            {
                plugin: 'vision',
                options: {
                    engines: { html: require('handlebars') },
                    path: path.join(__dirname, '../client/build')
                }
            },
            {
                plugin: require('./controllers/home'),
            },
        ],
    }
// controller/home
module.exports.register = function(server, options, next) {
server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
    directory: {
    path: path.join(__dirname, "../../../client/build/"),
    listing: false,
    index: ['index.html']
}

// the following handler serves the page but not the css or js
    //handler: (request, h) => {
    //    return h.file("index.html", {confine: false});
    //}

例如:

do echo $key $value
done < file_discriptor

答案 10 :(得分:0)

但是,如果元组大于关联数组可以容纳的k / v,该怎么办?如果是3或4个元素怎么办?可以对此概念进行扩展:

0  0  0  1
0  0  0  1
0  0  1  0
0  0  1  0

然后输出将类似于:

###---------------------------------------------------
### VARIABLES
###---------------------------------------------------
myVars=(
    'ya1,ya2,ya3,ya4'
    'ye1,ye2,ye3,ye4'
    'yo1,yo2,yo3,yo4'
    )


###---------------------------------------------------
### MAIN PROGRAM
###---------------------------------------------------
### Echo all elements in the array
###---
printf '\n\n%s\n' "Print all elements in the array..."
for dataRow in "${myVars[@]}"; do
    while IFS=',' read -r var1 var2 var3 var4; do
        printf '%s\n' "$var1 - $var2 - $var3 - $var4"
    done <<< "$dataRow"
done

现在元素的数量没有限制。不找票只是大声思考。 REF1REF2

答案 11 :(得分:0)

如果我的元组定义更复杂,我更希望将它们包含在heredoc中:

while IFS=", " read -ra arr; do
  echo "${arr[0]} and ${arr[1]}"
done <<EOM
c, 3
e, 5
EOM

这结合了looping over lines of a heredocsplitting the lines at some desired separating character