목록/배열이 있다고 가정해 보겠습니다.
list=(a b c)
각 요소를 xargs에 에코하는 방법은 무엇입니까? 그것은 다음과 같습니다:
for v in list; do echo v; done; | xargs
더 간단한 방법이 있나요?
답변1
printf '%s\n' "${list[@]}" | xargs
그러면 list
각 요소가 한 줄에 인쇄되고 개행으로 구분된 목록이 에 전달됩니다 xargs
.
"${list[@]}"
로 확장될 개별 큰따옴표 요소입니다 list
. printf
형식 문자열의 자리 표시자보다 더 많은 인수가 제공되면 해당 형식 문자열이 재사용됩니다.
그러나 이는 요소에 공백, 작은따옴표, 큰따옴표 또는 백슬래시 문자가 포함되어 있지 않고 빈 문자열이 아닌 경우에만 작동합니다(일부 xargs
구현은 텍스트로만 구성되어 있고 텍스트가 아니며 _
상대적으로 짧습니다).
임의의(너무 길지 않은 1) 요소(NUL 문자를 포함하지 않지만 현재 버전의 bash는 어쨌든 변수에 NUL을 저장할 수 없음)의 경우 xargs
대부분의 구현에서 지원하는 NUL로 구분된 레코드 옵션 으로 목록을 전달할 수 있습니다 -0
(Appearing POSIX 표준의 다음 버전에서):
{
[ "${#list[@]}" -eq 0 ] || printf '%s\0' "${list[@]}"
} | xargs
print0
도우미 기능을 사용하면 도움이 될 수 있습니다.
print0() {
[ "$#" -eq 0 ] || printf '%s\0' "$@"
}
print0 "${list[@]}" | xargs -0
NetBSD를 제외한 빈 목록의 경우 명령은 echo
(기본적으로) 인수 없이 한 번만 호출됩니다. 이 옵션을 사용하면 이러한 -r
상황을 피할 수 있습니다(POSIX 표준의 다음 버전에서도 마찬가지).
¹ 시스템 호출 제한을 xargs
해결하도록 설계되었지만 execve()
중간에 개별 인수를 제거하지 않으므로 단일 인수가 제한보다 크면 execve()
명령이 실행되지 않습니다. 또한 Linux에는 대부분의 시스템에 공통된 모든 매개변수 및 환경 변수의 누적 크기에 대한 전체 제한과 달리 개별 매개변수의 크기에 대한 제한이 있습니다.
답변2
특별히 긴 목록이 아니면 xargs
완전히 포기 해도 됩니다.
list=(a b c)
# With xargs
printf "%s\n" "${list[@]}" | xargs foo # Results in « foo a b c »
# Without xargs
foo "${list[@]}" # Also results in « foo a b c »
물론, 이를 귀하의 사례에 적용할 수 있는 여부는 xargs
실제 명령에 전달하려는 추가 플래그가 무엇인지에 따라 달라집니다.
이를 테스트 하려면 foo
이 스크립트를 실행하고 위의 모든 인스턴스를 foo
다음으로 바꾸십시오 ./foo
.
cat <<'EOF' > foo
#!/bin/bash
echo "Got $# arg(s): $*"
for ARG in "$@"; do echo "> $ARG <"; done
EOF
chmod a+x foo
또한 기본적으로(여기에 표시된 대로) xargs
해당 인수는 공백으로 분할되므로 다음과 같습니다.
list=('a b' c d) # Three arguments; the first contains a space
printf "%s\n" "${list[@]}" | xargs foo # Gives foo four arguments « a b c d »
foo "${list[@]}" # Gives foo three arguments, with the first containing a space, « 'a b' c d »