어떻게 분리되어 있는지에 관계없이 입력을 반복하고 명령을 실행하는 함수를 만들려고 합니다.
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[@]}"
또 다른 문제는 $2
두 번째 위치 매개변수만 포함되어 있고 세 번째, 네 번째, 다섯 번째 등을 반복하려고 한다는 것입니다. 모두 에 저장됩니다 $@
.
목표를 달성하려면 다음을 수행할 수 있습니다.
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
}
즉, 두 번째 매개변수를 통해 사용할 구분 기호를 지정해야 합니다. 예를 들면 다음과 같습니다.
$ 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
유틸리티를 사용하여 함수를 다시 구현할 수 있습니다(인수 중 하나에 개행 문자가 포함될 것으로 예상하지 않는 한, 이 경우 옵션을 로 조정해야 합니다 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
한 번에 하나의 작업을 강제로 실행합니다.