
どのように分離されているかに関係なく、入力を繰り返してコマンドを実行する関数を作成しようとしています。
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
ただし、これにはいくつかのバグがあります(カスタム区切り文字を指定すると、まだスペースで区切られます)。
答え2
コードに構文エラーがあります。関数呼び出しでは、配列を各要素に展開するリスト(個別に参照)をloop
使用します。これは表示されたループで実行されるアクションです。関数を呼び出すときに実行する必要があるアクションは次のとおりです。"${arr[@]}"
arr
for
loop echo "${arr[@]}"
また、関数は渡したコマンドの名前を選択し、残りの引数を繰り返す必要があります。
loop () {
local cmd=$1; shift
for arg do
"$cmd" "$arg"
done
}
ここでは、最初のパラメータを変数cmd
(コマンド)に割り当ててから、パラメータshift
リストからそのパラメータを削除します。引数リストには、繰り返したい文字列のみが含まれます。
次に、ループは残りの各引数に対してコマンドを順番に呼び出します。
これは制限された方法でユーティリティの目的を複製し、xargs
ユーティリティを使用して関数を再実装できます(引数の1つに改行文字が含まれると予想されない限り、この場合はオプションをに調整する必要がありますxargs
)。
loop () {
local cmd=$1; shift
printf '%s\n' "$@" | xargs -L 1 "$cmd"
}
xargs
ユーティリティはデータが標準入力を介して渡されることを期待するので、与えられた各引数をprintf
独自の行loop
に使用して印刷する準備をします(また、使用された各改行で区切られた引数xargs
に対して与えられたユーティリティを一度呼び出すように指示します-L 1
)。
これにより、where is some number of process to run in Parallel を使用してxargs
並列プロセスを開始するなど、実装の他の機能の一部を使用できます。-P n
n
テスト:
$ cat script.sh
loop () {
local cmd=$1; shift
printf '%s\n' "$@" | xargs -L 1 "$cmd"
}
arr1=(1 2 3)
arr2=("hello world" "home sweet home")
loop echo "${arr1[@]}"
loop echo "${arr2[@]}"
$ bash script.sh
1
2
3
hello world
home sweet home
答え3
ループはGNU Parallelと非常によく似ています。
declare -a arr=("1 a" "2 b" "3 c")
var1="1 a,2 b,3 c"
var2="1-a 2-b 3-c"
parallel -j1 echo ::: "${arr[@]}"
parallel -j1 -d , echo ::: "$var1"
parallel -j1 echo ::: $var2
-j1
一度に1つのジョブを強制的に実行します。