对于每个带有多个项目的数组

对于每个带有多个项目的数组

我正在编写一个下载东西的脚本。

在脚本中,我需要关联将重复下载的名称和 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

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

相关内容