是否可以在bash中循环元组?
作为一个例子,如果以下工作会很好:
for (i,j) in ((c,3), (e,5)); do echo "$i and $j"; done
是否有某种解决方法可以让我在元组上循环?
答案 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
答案 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 heredoc和splitting the lines at some desired separating character。