$(echo ...)를 사용하지 않는 한 for 루프에서 IFS 쉘 변수를 설정하여 문자열을 단어로 분할하는 것은 어떻습니까?

$(echo ...)를 사용하지 않는 한 for 루프에서 IFS 쉘 변수를 설정하여 문자열을 단어로 분할하는 것은 어떻습니까?

설정으로 인해 문자열이 , 및 의 세 단어로 분할 IFS='X'될 것이라고 가정합니다 .bashfooXbarXbazfoobarbaz

for그러나 명령 대체를 통해 문자열이 루프에 제공되는 경우에만 작동합니다 $(echo fooXbarXbaz).

$ IFS='X'; for x in fooXbarXbaz; do echo Y${x}Z; done
Yfoo bar bazZ
$ IFS='X'; for x in $(echo fooXbarXbaz); do echo Y${x}Z; done
YfooZ
YbarZ
YbazZ

첫 번째 예제 명령이 fooXbarXbaz세 단어로 분할되지 않는데 두 번째 예제에서는 성공하는 이유를 누군가 설명할 수 있습니까?

답변1

$IFS따옴표가 없는 확장 분사에만 사용됩니다. 에는 확장자가 없습니다 for x in fooXbarXbaz. 그러나 에는 따옴표가 없는 확장이 있습니다 . 이는 , 및 3개의 인수로 호출된다는 echo Y${x}Z의미입니다 . 유틸리티 는 각 인수 사이에 공백을 넣어 인쇄하므로 .echoYfoobarbazZechoYfoo bar bazZ

두 번째 예에서 문자열은 확장인 명령 대체의 출력이므로 문자열은 루프를 위해 분할됩니다.

이 변수는 유틸리티에 대한 입력을 IFS분할하는 데에도 사용됩니다 .read

답변2

fooXbarXbaz첫 번째 예제 명령을 세 단어 로 나눌 수 없는 이유를 누군가 설명할 수 있습니까?

쉘은 이렇게 작동하지 않기 때문에좀 더.

일부 고대에는 분사가 다음과 같은 간단한 단어에서도 발생했습니다.heirloom-sh:

heirloom-sh$ for foo in 123o456o789; do echo $foo; done
ech: not found
ech: not found
ech: not found

이런, 내 말은 다음과 같았습니다.

heirloom-sh$ for foo in 123o456o789; do "echo" $foo; done
123
456
789

(심지어 키워드와 변수 이름은 os로 구분되지 않습니다.)

oor Xin을 사용하는 것은 IFS다소 극단적이지만 현재 가장 좋은 시나리오는 분할이 다음에서만 발생한다는 것입니다.확장하다.

*의도적으로 분할을 사용하는 경우 따옴표가 없는 확장도 와일드카드 처리를 수행하므로 이와 같은 상황이 발생할 수 있다는 점을 명심하세요 . 배열은 일반적으로 여러 값을 처리하는 데 더 적합합니다.

답변3

GNU bash 문서는 이 동작을 명확하게 설명합니다.명령 대체

큰따옴표 내에서 대체가 발생하면 결과에 대해 단어 분리 및 파일 이름 확장이 수행되지 않습니다.

두 번째 경우에는 따옴표가 없는 대체 항목이 있으므로 fooXbarXbaz쉘은 set 값을 기반으로 결과 문자열을 토큰화하여 IFS단어를 여러 단어로 분할합니다.

첫 번째 경우 for x in fooXbarXbaz;문자열은 경로 이름 확장(전역 확장이라고도 함)을 거칩니다. 쉘은 가능한 모든 확장이 완료된 후 어휘집보다 훨씬 나중 단계에서 이 작업을 수행합니다(참조쉘 확장), 결과 문자열은 문자 그대로 처리됩니다.

경로 이름 확장 전에 발생하는 변수 확장 사례를 추가하려면 $varOP와 동일한 프로세스를 수행하십시오.

IFS='X'; var=fooXbarXbaz; for x in $var; do echo Y${x}Z; done

따옴표가 없는 변수 확장(예: 명령 대체)은 값을 기준으로 단어 분할을 수행합니다 IFS. 이것이 바로 우리가 셸에 의한 예상치 못한 토큰화를 피하기 위해 일반적으로 모든 확장을 인용해야 한다고 주장하는 이유입니다.

관련 정보