配列があるとしましょう。a=(foo 'bar baz')
各配列要素にコマンド/関数を適用し、結果の文字列を別の配列に格納するよりも確実な方法はありますか?
b=()
for e in $a; do
b+=("$(my_cmd "$e")")
done
答え1
これに対する関数はいつでも宣言できます。
map() {
local arrayname="$1" cmd="$2" i
shift 2
eval "$arrayname=()"
for i do
eval "$arrayname+=(\"\$($cmd)\")"
done
}
次のように使用されます。
$ a=(a '' bcd)
$ map b 'wc -c <<< "$i"' "$a[@]"
$ echo $b
2 1 4
答え2
コマンドが配列要素に対して何をするのかを事前に知っている場合は、次のことができます。パラメータ拡張フラグコマンド出力をアレイに適用する方法については、(参照man zshexpn
)zsh
はい
配列にa
ファイル名が含まれており、各ファイル名には1行のテキストしか含まれていないとします。
$ a=(foo 'bar baz')
$ cat foo
A
$ cat 'bar baz'
B C
今、議論のために、コマンドが単にファイルの内容をcat
配列に入れるとしましょう。b
この場合、繰り返すのではなく、単に次のように書くことができます。
b=(${(f)"$(cat "${a[@]}")"})
ここで(f)
、結果はcat
改行文字で区切られた単語に分割されます。
結果は予想通りです。
$ echo "${b[1]}"
A
$ echo "${b[2]}"
B C
実際の状況に応じて、フラグを使用して他の文字を分割することができますps:<character>:
。(ps:\n:)
上記の例の改行文字やNULL文字など、一部の文字にはそれぞれ、および省略形(ps:\0:)
があります。(f)
(0)
答え3
次のことができます。
eval "b=(" '"$(cmd "$a['{1..$#a}']")"' ")"
しかし、これはあまり明確ではありません。
答え4
注:
以下を使用して短縮できます。
for e ($a) b+=("$(my_cmd "$e")")
ループ$a
はnull以外の要素を繰り返します。すべての要素を繰り返すには"$a[@]"
。