wsl.exe를 사용하여 cygwin bash 및 oh-my-zsh에서 이 문제를 재현할 수 있습니다. 내 의도는 명령줄에서 다음 두 줄을 실행하는 것입니다.
npm rm plugin-alias
npm i -D plugin-alias
나는 이것을하려고 노력하고 있습니다 :
echo -ne "rm\0i -D\0" | xargs -t -0 -IREPLACE npm REPLACE plugin-alias
잘 달리고 있어요 rm
. -t
실행 중이라고 합니다 npm rm plugin-alias
. 하지만 i -D
오류:
npm 'i -D' plugin-alias
Unknown command: "i -D"
i -D
xargs가 여러 인수로 전달되어 실행되도록 하는 방법이 있습니까 npm i -D plugin-alias
?
,
구분 기호를 and 로 변경해 보았지만 \n
차이가 없는 것 같습니다.
따옴표를 제거 해야 한다면 sed
그렇게 하십시오. 하지만 xargs
이로 인해 발생하는 문제가 해결되기를 바랍니다.
업데이트: @muru가 유용한 의견을 제공했습니다.
@muru: 실제 인용문은 포함되어 있지 않습니다.
나: 그러면 왜 알 수 없는 명령: "i -D"라는 오류 메시지가 표시되나요?
@muru: xargs는 i -D를 다음과 같이 제공하기 때문입니다.단일 인수npm으로.
이제 이해했으므로 제목을 더 정확하게 편집할 수 있습니다. 더 나은 검색 가능성을 위해 원래 제목은 "xargs가 공백이 있는 항목을 인용하는 이유와 이를 방지하는 방법은 무엇입니까?"였습니다.
답변1
답변:
xargs: 각 줄에 대해 명령을 실행하고 인수를 공백으로 구분하시겠습니까?
테마에서 이것이 바로 -L
¹ 옵션이 사용되는 용도입니다.
xargs -L1 cmd << 'EOF'
1 2 3
first 'second arg'
"a 1" b\
2
EOF
cmd
각각 실행됩니다1
L
이네입력(논리적 줄, 두 번째 매개변수에 포함된 개행 문자를 인용하고 후행 공백을 사용하면 긴 줄을 나눌 수 있으므로 세 번째 줄은 두 개의 물리적 줄로 구성되어 있음을 알 수 있습니다), 각 줄을 다음으로 분할합니다. 논쟁을 중심으로.
-I
그러나 GNU 스타일과 결합할 수는 없습니다 -0
.
이것은 어떤 형태의 인용을 이해하기 때문에(구문은 현대 쉘의 구문과 다르다는 점에 유의하세요) 임의의 인수를 지정할 수 있도록 허용하므로(제한사항은 구현에 따라 다름²) -0
.
BSD의 경우 xargs
while과 결합하여 -J
다음을 수행할 수 있습니다.
xargs -rL1 -J {} npm {} plugin-alias << 'EOF'
rm
i -D
EOF
다른 구현의 경우 다음을 사용하여 sh
매개변수 순서를 변경할 수 있습니다.
xargs -L1 sh -c '[ "$#" -eq 0 ] || exec npm "$@" plugin-alias' sh << 'EOF'
rm
i -D
EOF
(여기서는 [ "$#" -eq 0 ] ||
비표준 대체품 으로도 사용됩니다 -r
).
1 GNU xargs
에는 더 이상 사용 되지 -l
않는 비표준 가 하나 이상 있습니다 -L 1
. -l
예를 들어 와 같이 여러 줄을 사용할 수도 있지만 ; 대신 -L
옵션에 추가해야 합니다. 또는 ).-l1
-l 1
-L1
-L 1
² 예를 들어, 일부는 텍스트가 아닌 입력을 방해하고, 일부는 명령줄 길이 또는 개별 인수에 대한 제한이 극히 낮으며, 일부는 _
파일 끝을 이해합니다... 또한 구분 기호로 인식되는 문자 목록은 다음에 따라 다릅니다. 일부의 구현 및 로케일 설정.
답변2
일반적으로 사용을 권장하지 않습니다. 이에 대해 셸의 토큰화를 적용할 수 있습니다.
printf "rm\0i -D\0" |
xargs -t -0 -I{} sh -f -c 'npm $1 plugin-alias' sh {}
sh
여기서는 NUL로 구분된 각 문자열을 단일 인수로 스크립트 에 전달하고 있으며 , 따옴표 없이 확장 $1
하면 공백으로 분할됩니다. 옵션 -f
(에 대한 set -f
)은 와일드카드를 비활성화합니다.
스크립트를 사용하여 다양한 명령줄 매개변수를 명확하게 확인하세요.
% printf "rm\0i -D\0" |
xargs -t -0 -I{} sh -f -c './args.sh npm $1 plugin-alias' sh {}
sh -f -c ./args.sh npm $1 plugin-alias sh rm
3 args: <npm> <rm> <plugin-alias>
sh -f -c ./args.sh npm $1 plugin-alias sh i -D
4 args: <npm> <i> <-D> <plugin-alias>
또는 -L
NUL 구분 기호를 개행 문자로 변경하면 원하는 대로 할 수 있다고 생각합니다. 그러나 -I
공백 분할이 비활성화된 것처럼 보이기 때문에 올바른 순서로 인수를 얻으려면 여전히 셸이 필요한 것 같습니다 .
% printf 'rm\ni -D\n' |xargs -L1 sh -c './args.sh npm "$@" plugin-alias' sh
3 args: <npm> <rm> <plugin-alias>
4 args: <npm> <i> <-D> <plugin-alias>
어쨌든 버전 간에 차이가 있는지는 잘 모르겠지만 xargs
쉘을 사용하여 동일한 작업을 수행할 수 있습니다.
$ printf 'rm\ni -D\n' | while read -r line ; do set -f; ./args.sh npm $line plugin-alias; done
3 args: <npm> <rm> <plugin-alias>
3 args: <npm> <i -D> <plugin-alias>
args.sh
이 스크립트는 다음과 같습니다.
#!/bin/sh
if [ "$#" != 0 ]; then
printf "%d args: " "$#"
printf "<%s> " "$@"
echo
else
printf "no args.\n"
fi
답변3
xargs
여기서는 를 사용하는 대신 쉘이 목록을 읽도록 할 수 있습니다. 그리고 zsh
:
while IFS=, read -rd '' -u3 -A args; do
npm "$args[@]" plugin-alias
done 3< <(printf '%s\0' rm i,-D)
,
빈 매개변수를 더 쉽게 지정할 수 있도록 여기에서 매개변수를 구분합니다 .
이것은 표시하려는 목록의 목록입니다. 외부 명령에 대한 임의 인수의 단일 목록은 NUL 문자로 구분하여 표시할 수 있습니다. 명령 인수에는 NUL 문자를 포함할 수 없다는 제한이 있기 때문입니다(bash 내장 및 함수에 대한 인수에는 동일한 제한이 있지만 zsh의 인수에는 적용되지 않음). ), 그러나 임의의 요소 목록을 나타내려면 단일 구분 기호에 의존할 수 없으며 특정 형식의 인코딩을 사용해야 합니다.
read
한 가지 옵션은 없이 사용하는 것입니다 -r
. 예를 들어 위 옵션을 제거하면 -r
2개의 목록을 나타낼 수 있습니다. 첫 번째 목록에는 빈 문자열이 포함되고 foo,bar
두 번째 목록에는 줄 바꿈 및 백슬래시가 포함됩니다.
printf '%s\0' ',foo\,bar' '
,\\'
,
및 \
에 있는 동안 접두사를 기억해야 합니다 \
.
에서는 zsh
빈 레코드가 빈 요소로 분할됩니다. Bash 또는 ksh에는 요소가 전혀 없으며 2개의 레코드 와 빈 요소 foo,
로 분할됩니다 . foo
또한 를 로 대체 bash
해야 합니다 .-a
-A