どのように分離されているかに関係なく、入力を繰り返してコマンドを実行する関数を作成しようとしています。
function loop {
# Args
# 1: Command
# 2: Inputs
for input in "$2" ; do
$1 $input
done
}
declare -a arr=("1" "2" "3")
$ loop echo "$arr[@]"
1
$ loop echo 1 2 3
1
$ loop echo $arr
1
しかし、それによるとこれ答えはfor .. in ..
配列で機能します。
for item in "${arr[@]}" ; do
echo "$item"
done
スペースで区切られた値でも機能します。
for item in 1 2 3 ; do
echo "$item"
done
簡単に言えば、パラメータを渡すと"${arr[@]}"
効果をどのように取得できますか?1 2 3
\n
また、この繰り返しの概念をファイルなどの区切りコンテンツなど、あらゆる種類の区切り項目に拡張できますか? Pythonには概念がありますiterators
。 bashにも似ていますか?
ベストアンサー1
配列が正しく呼び出されませんでした。 $arr
配列の最初の要素にのみ拡張され、$arr[@]
リテラル文字列が追加される最初の要素に展開されます[@]
。
配列のすべての要素を呼び出すには、次のようにします。"${arr[@]}"
もう1つの問題は、$2
2番目の位置パラメータのみが含まれており、3番目、4番目、5番目などを繰り返すことです。すべてに保存されます$@
。
目標を達成するには、次のようにします。
function loop {
local command=$1
shift
for i in "$@"; do
"$command" "$i"
done
}
これは、最初の位置引数に設定され、残りのcommand
位置$@
引数を繰り返すために使用できるように移動されます。その後、配列を正しく呼び出すだけです。
$ declare -a arr=("element1" "element2" "element3")
$ loop echo "${arr[@]}"
element1
element2
element3
$ loop printf 'hello ' 'world\n'
hello world
$ loop touch file1 file2 file3
$ ls
file1 file2 file3
この関数がさまざまな区切り文字を受け入れるようにするには、次のようにします。
function loop {
local command=$1
local delim=$2
shift 2
set -- $(tr "$delim" ' ' <<<"$@")
for i in "$@"; do
"$command" "$i"
done
}
つまり、2番目のパラメータで使用する区切り文字を指定する必要があります。たとえば、次のようになります。
$ loop echo '|' 'one|two|three'
one
two
three
$ loop echo '\n' "$(printf '%s\n' 'one' 'two' 'three')"
one
two
three
ただし、これにはいくつかのバグがあります(カスタム区切り文字を指定すると、まだスペースで区切られます)。