설정으로 인해 문자열이 , 및 의 세 단어로 분할 IFS='X'
될 것이라고 가정합니다 .bash
fooXbarXbaz
foo
bar
baz
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
의미입니다 . 유틸리티 는 각 인수 사이에 공백을 넣어 인쇄하므로 .echo
Yfoo
bar
bazZ
echo
Yfoo 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
(심지어 키워드와 변수 이름은 o
s로 구분되지 않습니다.)
o
or X
in을 사용하는 것은 IFS
다소 극단적이지만 현재 가장 좋은 시나리오는 분할이 다음에서만 발생한다는 것입니다.확장하다.
*
의도적으로 분할을 사용하는 경우 따옴표가 없는 확장도 와일드카드 처리를 수행하므로 이와 같은 상황이 발생할 수 있다는 점을 명심하세요 . 배열은 일반적으로 여러 값을 처리하는 데 더 적합합니다.
답변3
GNU bash 문서는 이 동작을 명확하게 설명합니다.명령 대체
큰따옴표 내에서 대체가 발생하면 결과에 대해 단어 분리 및 파일 이름 확장이 수행되지 않습니다.
두 번째 경우에는 따옴표가 없는 대체 항목이 있으므로 fooXbarXbaz
쉘은 set 값을 기반으로 결과 문자열을 토큰화하여 IFS
단어를 여러 단어로 분할합니다.
첫 번째 경우 for x in fooXbarXbaz;
문자열은 경로 이름 확장(전역 확장이라고도 함)을 거칩니다. 쉘은 가능한 모든 확장이 완료된 후 어휘집보다 훨씬 나중 단계에서 이 작업을 수행합니다(참조쉘 확장), 결과 문자열은 문자 그대로 처리됩니다.
경로 이름 확장 전에 발생하는 변수 확장 사례를 추가하려면 $var
OP와 동일한 프로세스를 수행하십시오.
IFS='X'; var=fooXbarXbaz; for x in $var; do echo Y${x}Z; done
따옴표가 없는 변수 확장(예: 명령 대체)은 값을 기준으로 단어 분할을 수행합니다 IFS
. 이것이 바로 우리가 셸에 의한 예상치 못한 토큰화를 피하기 위해 일반적으로 모든 확장을 인용해야 한다고 주장하는 이유입니다.