내가 아는 한, Bourne 쉘과 파생 클래스에서는 IFS=
IFS가 null로 설정되어 쉘이 필드 분할을 수행하지 않습니다.
나는 읽은 것을 기억합니다 :
echo "$*"
IFS= echo "$*"
uname -o
이 두 명령을 CentOS에서 한 번, WSL에서 한 번( =GNU/Linux에만 해당하므로 배포판을 알 수 없음) 실행하면 빈 줄만 표시됩니다.
위의 테스트 명령은 무엇을 의미하며, 이것이 실제로 IFS 학습을 위한 좋은 예입니까(그렇지 않다면 어떤 간단한 두 줄 테스트를 제안하시겠습니까)?
답변1
답변하기 전에 경고 사항이 있습니다. 변화는 IFS
종종 매우 혼란스러운 결과를 초래할 수 있습니다. 상대적으로 안전하고 명확한 효과(예: read
및 같은 명령에 대해 설정하는 등 IFS= read -r line
) 가 있는 곳이 있지만 IFS=, read -r field1 field2 field3
일반적인 동작을 이해하려고 노력하는 것은 가치 있는 것보다 더 많은 작업입니다. 또한 이를 변경하는 경우에는 앞에 할당을 붙여서 특정 명령으로 분리하거나( 다시 에 표시된 대로) IFS= read -r line
변경해야 하는 즉시 다시 일반 명령으로 설정하십시오.
이제 문제는 다음과 같습니다. 이는 효과의 좋은 IFS
예가 아닙니다. 우선 $*
현재 인수 목록으로 확장되고 대화형 쉘에는 일반적으로 인수가 없으므로 빈 문자열로 확장되기 때문입니다. set
필요한 경우 명령을 사용하여 변경할 수 있습니다. 예는 다음과 같습니다.
$ echo "$*"
$ set -- "foo bar" "baz/quux"
$ echo "$*"
foo bar baz/quux
둘째, IFS
접두사를 특정 명령으로 변경하는 경우(에서와 같이 IFS= echo "$*"
) 해당 명령이 실행될 때만 영향을 미치며 쉘이 인수를 확장할 때는 발생하지 않습니다.앞으로명령 자체), echo
그 자체는 영향을 받지 않습니다 IFS
( IFS
설정에 관계없이 항상 인수를 공백으로 붙입니다). 예를 들어:
$ IFS= echo "$*" # No effect, because IFS is only set for echo, which ignores it
foo bar baz/quux
이것을 IFS
쉘 자체의 설정과 비교하십시오.
$ saveIFS=$IFS # Save the normal IFS, so we can set it back later
$ IFS= # Set IFS for the entire shell
$ echo "$*" # Now we'll see an effect
foo barbaz/quux
$ IFS='+-*/' # Let's try another value
$ echo "$*" # Now the arguments get merged, first char of IFS beween them
foo bar+baz/quux
$ echo $* # See below
foo bar baz quux
$ printf '%s\n' $* # See below
foo bar
baz
quux
$ IFS=$saveIFS # Set it back to normal, to avoid trouble later
그렇다면 "+-*/"가 나타나면 echo $*
어떻게 될까요 ? IFS
글쎄, IFS
그들은 모두 병합에 사용됩니다.그리고인수를 분할하므로 with 와 마찬가지로 echo "$*"
비트 $*
는 로 확장되지만 foo bar+baz/quux
큰따옴표로 묶이지 않았기 때문에 즉시 단어로 분할됩니다(모두) IFS
이므로 "foo bar", "baz" 및 "quux"의 세 가지 인수로 분할된 echo
다음 echo
그 사이에 공백을 넣어 모두 함께 붙입니다. 기본적으로 이 명령에서도 동일한 일이 발생합니다 printf
. 단, 형식 문자열로 인해 다음 각 인수가 별도의 줄에 인쇄되므로 "foo bar"는 하나의 인수일 뿐임을 알 수 있습니다.
그런데 어떤 사람들은 saveIFS
내가 여기서 사용하는 것과 같은 방법을 사용하고, 어떤 사람들은 unset IFS
쉘이 작동하게 만드는 이후에 사용하는 것을 선호합니다.마치 IFS
일반 space-tab-newline 값으로 되돌립니다. 둘 다 작동하지만함께 있지 않다. 나중에 저장하고 복원하려고 하면 unset IFS
빈 문자열로 설정되어 상황이 이상해집니다. 다음을 IFS=$' \t\n'
사용하여 명시적으로 재설정할 수도 있습니다.진짜지원되지 않는 쉘에서는 이상한 효과가 발생할 수 있습니다 $' '
.) 한숨을 쉬다.
편집 : 참조이 문제값을 저장하고 복원하는 방법에 대한 추가 옵션 및 토론 IFS
.
BTW2, 대부분의 경우 매개변수를 병합하거나 분할하는 것을 원하지 않으므로 원하는 것은 과 "$@"
달리 매개변수를 병합하지 않으며 큰따옴표를 사용할 때 매개변수를 분할하지 않습니다(또는 확장됩니다). 파일 이름 와일드카드) - 그냥 직접 전달합니다. 그러나 을 사용하지 마십시오 . 실제로는 이렇게 병합하기 때문입니다 (또는 쉘에 따라 첫 번째 문자 대신 ""를 사용하여 병합할 수도 있음 )(일반 변수에 저장하려면 병합해야 함). 대신 을 사용하여 배열로 저장하세요.$*
$@
args="$@"
"$*"
IFS
args=("$@")