我正在编写一个下载东西的脚本。
在脚本中,我需要关联将重复下载的名称和 URL(因此是脚本)
name1,url1
name2,url2
name3,url3
command $NAME $URL
所以我想要一个 for every 循环来遍历我的名称列表和各自的 url。实现这一目标的最佳方法是什么?目前对将这些列表保存在外部文件或其他任何内容中不感兴趣。在脚本中是我想要的示例。
答案1
bash
在这方面是相当有限的。您可能想尝试其他 shell。
使用zsh
(您已经在使用zsh
语法,因为您没有在 中引用变量command $NAME $URL
):
for name url (
name1 url1
name2 url2
name3 url3
) command $name $url
使用bash
POSIX shell 或其他 POSIX shell,您可以执行以下操作:
while IFS=, read <&3 -r name url; do
{
command "$name" "$url"
} 3<&-
done 3<< "EOF"
name1,url1
name2,url2
name3,url3
EOF
这意味着这些值不能包含逗号或换行符。
最新版本bash
还支持关联数组,使用的语法看起来更像 ksh93 而不是zsh
.因此,如果名称是唯一的,您可以这样做:
typeset -A pairs
pairs=(
[name1]=url1
[name2]=url2
[name3]=url3
)
for name in "${!pairs[@]}"; do
url=${pairs[$name]}
command "$name" "$url"
done
这也适用于ksh93
.请注意,两者之间的引用规则略有不同。在 中zsh
,关联数组定义语法更加简单,并且适用正常的引用规则:
pairs=(name1 url1 name2 url2 name3 url3)
您可以将其放在几行中:
pairs=(
name1 url1
name2 url2
name3 url3
)
2021年编辑:注意zsh
现在还支持hash=([key]=value)
ksh93语法,bash
现在支持hash=(key value)
zsh语法
请注意,顺序不会保留,并且bash
关联数组不支持空键。
ksh93
支持多维数组,所以你可以这样做:
pairs=((name1 url1) (name2 url2) (name3 url3))
for ((i = 0; i < ${#pairs[@]}; i++)); do
name=${pairs[i][o]} url=${pairs[i][1]}
command "$name" "$url"
done
或 NUL,尽管 NUL 不能传递给通过系统execve()
调用执行的命令,严格来说,姓名部分不能包含逗号,但网址部分可以,只要至少有 2 个,或者如果只有一个,它就不在最后,因为方式$IFS
被解释为在除 之外的壳中分裂zsh
。
答案2
您可以创建一个此处文档,将其写入临时文件然后进行处理。临时文件将自动删除,因此无需手动清理。
#!/bin/bash
mylist=/var/tmp/$$
trap 'rm -f ${mylist}' EXIT
cat << _EOF_ > ${mylist}
name1 url1
name2 url2
name3,url3
_EOF_
while read name url
do
printf "%s %s\n" ${name} ${url}
done < ${mylist}
答案3
一开始我就想到了像关联数组这样复杂的东西。
然后我意识到,考虑到您的名称与网址一样多,可以像下面这样简单地完成:
root@debian:a=( "name1,url1" "name2,url2" "name3,url3" );while IFS="," \
read -r name url;do echo "command $name $url";done<<<$(printf '%s\n' "${a[@]}")
command name1 url1
command name2 url2
command name3 url3
您所需要做的就是将名称和 url 一起存储在同一个数组中(我的测试中为 a),并用逗号分隔。
答案4
也许一个简单的 bash 脚本适合你:
pairs=( "name1,url1" "name2,url2" "name3,url3" )
for pair in "${pairs[@]}"; do
IFS=, read name url <<<"${pair}"
printf "%s %s\n" "${name}" "${url}"
command "${name}" "${url}"
done