단어 분할 내 인용문을 볼 수 없습니다. for arg in

내가 이것을 가지고 있다고 상상해 보라.

$ ARGS='"a b" c'
$ for arg in "$ARGS"; do echo "$arg"; done
"a b" c
$ for arg in $ARGS; do echo "$arg"; done
"a
b"
c

내가 얻고 자하는 결과는

$ <???>
a b
c

나는 이것에 대해 어떻게 갈 것인가?
감사.



답변

이렇게하면 다음과 같은 결과를 얻을 수 있습니다.

eval "for arg in $ARGS; do echo \"\$arg\";done"

그러나 eval은 최후의 수단으로 사용해야합니다. 질문에 대답하기 어려운 이유는 ARGS 변수 형식이 잘못 설계 되었기 때문입니다.

공백 문자로 구분 된 일련의 단어는 인용 메커니즘으로 보호되는 단어 안에 공백을 포함하고 있으며 쉘 명령의 기본 형식입니다. 쉘 스크립트를 작성할 수 있으려면이 형식을 배워야하기 때문에 쉘 스크립트가 관리하는 데이터 구조에이 형식을 사용하려는 유혹이 발생하므로 쉘과 유사한 구조 "a b" c 그것을 셸 변수에 채 웁니다.

이것은 대개 나쁜 생각입니다. 셸 스크립트의 문자열이 셸 명령 줄처럼 보이지 않아도되며 공백으로 구분되는 어쩌면 인용 된 단어가 포함 된 문자열을 조작하는 유일한 방법은 기본 문자열 작업으로 자신의 파서를 작성하거나 쉘은 eval로 그것을 수행합니다.

그러나 eval을 사용하면 편리한 단어 분리기와 따옴표 제거기를 얻지 않고 명령 대체, 매개 변수 대체, 입출력 방향 재 지정 및 기타 수행 할 일들과 같은 셸 구문 분석기를 모두 얻을 수 있습니다. 그러고 싶지 않아.

배열을 사용하십시오. 이 배열 기반 스크립트는 zsh, ksh 및 bash에서 작동합니다.

ARGS=("a b" c)
for arg in "${ARGS[@]}"; do
    echo "$arg"
done

그것은 eval보다 훨씬 깔끔합니다. zsh, ksh 또는 bash가없는 고대 시스템을 프로그래밍하고 있다면 awk를 배워보십시오. 최소한의 POSIX 셸은 배열을 필요로하는 복잡한 스크립트의 언어가 아닙니다.

ormaaj의 대답에 대한 약간의 정교함 : POSIX sh에는 하나의 배열 변수가 있습니다 : $@ 이것은 “위치 매개 변수”(명령 행 인수)의 배열입니다. 개별 요소에 액세스 (읽기, 쓰지 않음) 할 수 있습니다. $1, $2, $3, 등등. 당신은 전체 어레이를 set 명령. 샘플 스크립트의 경우이 기능만으로도 충분합니다. 이 기능은 Bourne 제품군의 모든 쉘에서 작동합니다.

set -- "a b" c
for arg; do
    echo "$arg"
done

거기에 보너스 기능 데모를 추가했습니다. for arg ~없이 in 같음 for arg in "$@" 그것은 $@ 정렬.


답변

따옴표에 관심이 없으므로 문자열을 처리하기 전에 sed를 사용하여 따옴표를 제거하십시오.

for arg in `echo $ARGS | sed -e 's/"//g'`; do
  echo $arg
done

않는 한 … 당신의 예제가 잘못되어 다음과 같은 것을보고 싶지 않은 한 :

a b
c

아마 이렇게하는 방법은 많이 있지만 awk (GNU awk를 가정하면 한 문자보다 긴 필드 구분 기호를 사용할 수 있습니다)를 사용합니다.

echo $ARGS | \
awk -F'" ' '{ for (field = 1; field <= NF; field++) print $field; }' | \
sed -e 's/^"//' -e 's/"$//'

마지막 sed는 $ ARGS가 끝날 때 여는 따옴표와 닫는 따옴표를 제거합니다. 물론 중첩 된 따옴표를 사용하면이 모든 문제가 해결됩니다.