複数の項目を含む各配列の場合

複数の項目を含む各配列の場合

私はものをダウンロードするスクリプトを書いています。

スクリプトから繰り返しダウンロードされる名前とURL(したがってスクリプト)を関連付ける必要があります。

name1,url1
name2,url2
name3,url3


command $NAME $URL

だから私は名前リストとそのURLリストを繰り返すためにすべてのループが欲しいです。これを達成するための最良の方法は何ですか?現在、このリストを外部ファイルや他の場所に保存することに興味はありません。スクリプトには私が望むものの例があります。

答え1

bashこれに関しては非常に限られています。他のシェルを試してみることもできます。

使用してください(で変数を引用していないので、すでにzsh構文を使用しています)。zshcommand $NAME $URL

for name url (
  name1 url1
  name2 url2
  name3 url3
) command $name $url

bashPOSIXシェルまたは他のPOSIXシェルを使用すると、次のことができます。

while IFS=, read <&3 -r name url; do
  {
    command "$name" "$url"
  } 3<&-
done 3<< "EOF"
name1,url1
name2,url2
name3,url3
EOF

これは、値にカンマや改行文字を含めることができないことを意味します。

最新バージョンでは、bashksh93と同様の構文を使用して連想配列もサポートしていますzsh。したがって、名前が一意の場合は、次のことができます。

typeset -A pairs
pairs=(
  [name1]=url1
  [name2]=url2
  [name3]=url3
)
for name in "${!pairs[@]}"; do
  url=${pairs[$name]}
  command "$name" "$url"
done

これも適用されますksh93。引用規則は2つの間で若干異なります。では、zsh連想配列定義の構文がより簡単で、一般的な引用規則が適用されます。

pairs=(name1 url1 name2 url2 name3 url3)

次のように数行で入力できます。

pairs=(
  name1 url1
  name2 url2
  name3 url3
)

2021年編集:ksh93構文がzshサポートされ、zsh構文もサポートされます。hash=([key]=value)bashhash=(key value)

順序は維持されず、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

execve()あるいは、NUL、厳密に言えば、NULはシステムコールを介して実行されるコマンドに渡すことはできません。名前セクションにカンマを含めることはできませんが、URL部分は2つ以上であれば大丈夫で、1つだけあっても終わりではありません。その方法は、$IFS1つを除いてはシェルで分割するものと解釈されるからです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

最初は、連想配列と同じくらい複雑なことを考えました。
その後、URLほど名前が多いことを考えると、次のように簡単に実行できることに気づきました。

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

関連情報