중첩된 셸 스크립트는 목록 변수에서 작동하지 않습니다.

중첩된 셸 스크립트는 목록 변수에서 작동하지 않습니다.

다음 두 개의 최소 쉘 스크립트를 만들었습니다.

테스트 1

#!/usr/bin/env bash

letterList=$1

for letter in $letterList
do
    echo $letter
done

그리고 두 번째

테스트 2

#!/usr/bin/env bash

letterList=$1

test1 $letterList

실행하면 원하는 출력 을 test1 'A B C'얻은 A다음 .BC

그러나 실행하면 발생할 것으로 test2 'A B C'예상되지만 test1 'A B C'실제 출력은 A.

따라서 중첩된 변수 목록이 읽혀지지 않는 것, 즉 실행되는 것처럼 보입니다 test1 A.

무슨 일이 일어나고 있으며 어떻게 원하는 결과를 얻을 수 있습니까?

추신: 관련이 있다면 OS X를 사용하고 있습니다.

답변1

코드에 목록 변수가 없습니다. 당신은 밧줄을 가지고 있습니다.

test1따옴표가 없는 확장을 사용하는 호출입니다 $letterList. 이로 인해 쉘은 해당 값을 공백, 탭 및 줄 바꿈(기본적으로)에서 여러 단어로 분할하고 각 단어에 파일 이름 와일드카드가 포함된 경우 파일 이름 와일드카드가 됩니다. 결과 단어는 test1별도의 인수로 전달됩니다.

에서는 test1이러한 매개변수 중 첫 번째를 에 넣습니다 letterList.

$letterList문자열을 test1from as is 에 전달 하려면 test2호출 시 확장을 큰따옴표로 묶어야 합니다.

test1 "$letterList"

그런데 당신은의지하다$letterList루프의 값 분할은 셸에서 수행되지만 test1(문제를 일으키는 동일한 메커니즘) 코드가 실수로 파일 이름 글로빙을 수행하는 것을 방지할 수는 없습니다(예를 들어 스크립트를 테스트하여 test2 "A B C *"무슨 뜻인지 확인).


합격하고 싶다면목록단일 문자열 대신 test2문자열 대신 목록을 사용하여 호출합니다.

test2 A B C "Hello World" "* *"

그런 다음 에서 test2매개변수를 다음으로 전달합니다 test1.

#!/bin/sh

test1 "$@"

여기에서는 "$@"위치 인수(스크립트에 대한 매개변수) 목록이 확장되고 각 개별 인수가 참조됩니다. 이는 이와 같은 매개변수가 Hello World호출 시 여러 매개변수로 분할되지 않고 test1문자열이 * *둘로 분할되지 않으며 파일 이름 일치가 발생하지 않음을 의미합니다.

에서 test1매개변수를 반복합니다.

#!/bin/sh

for arg in "$@"; do
    printf '%s\n' "$arg"
done

또는

#!/bin/sh

for arg do
    printf '%s\n' "$arg"
done

...또는 매개변수만 인쇄하려는 경우에는

#!/bin/sh

printf '%s\n' "$@"

/bin/sh여기에는 특정 항목이 없기 때문에 전체적으로 쉘로 사용하고 있습니다 bash.

답변2

./test2 'a b c'실행하면 다음을 얻습니다.

$1=a b c

따라서 마지막 줄은 다음과 같습니다.

test1 a b c

실행 하면 test1다음을 얻습니다:

$1=a
$2=b
$3=c

즉, 주어진 매개변수는 test1따옴표로 묶이지 않으므로 하나가 아닌 세 개의 매개변수가 됩니다.

test1단일 매개변수를 전달하려면 변수를 큰따옴표로 묶으면 됩니다. 즉, 마지막 줄을 다음 test2으로 바꿉니다.

./test1 "$letterlist"

../.$PATH

답변3

실제 목표가 무엇인지는 확실하지 않습니다. 당신이 명확하게 말하는 유일한 것은 세 개의 개별 라인 및 에 test2 'A B C' 출력을 원한다는 것입니다 A.BC

그러한 결과를 제공할 수 있는 다른 솔루션이 있습니다. 일반적으로 출력은 다음과 비슷해 보입니다. 켈룸의 답변.

  • test2동일하게 유지하십시오 .
  • test1다음과 같이 변경합니다 .

    #!/bin/sh
    
    for letter in $*
    do
        printf '%s\n' "$letter"
    done
    

    그러면 자연스럽게 행동이 바뀔 것입니다 test1. 이제 $1. 따라서 , , 및 (  단지 , 및 대신 )  이 test1 'A B C' 'D E F'6개의 개별 라인에 출력됩니다 .ABCDEFABC

$*공백이 포함된 문자열을 별도의 단어로 분리하므로 일반적으로 사용을 권장하지 않습니다 . 예를 들어 "lazy dog"두 단어(매개변수)가 됩니다. 그러나 이것은 정확히 당신이 원하는 행동인 것 같습니다.

printfecho파일 이름의 시작 부분보다 약간 안전합니다.-또는 포함되어 있습니다 \. 이 사이트에서는 이미 이에 대해 자세히 설명하고 있습니다. 더 알고 싶으시면 검색해 보세요.

관련 정보