bash에서을 가지고 있다고 말하면 var=a.b.c.
다음과 같습니다.
$ IFS=. printf "%s\n" $var
a.b.c
그러나 이러한 사용법은 IFS
배열을 만드는 동안 적용됩니다.
$ IFS=. arr=($var)
$ printf "%s\n" "${arr[@]}"
a
b
c
이것은 매우 편리하지만 확실하게 문서화되어 있습니까? Bash 문서의 배열 또는 단어 분할 섹션을 빠르게 읽 더라도 어느 쪽도 지시하지 않습니다. 단일 페이지 문서IFS
를 검색 해도이 효과에 대한 힌트는 제공되지 않습니다.
언제 안정적으로 할 수 있는지 잘 모르겠습니다.
IFS=x do something
그리고 이것이 IFS
필드 분할에 영향을 미칠 것으로 예상합니다 .
답변
기본 아이디어는 when 가 외부 명령 일 때 실행 하도록 VAR=VALUE some-command
설정 VAR
되어 VALUE
있으며, 그보다 더 화려하지는 않습니다. 이 직관을 쉘 작동 방식에 대한 지식과 결합하면 대부분의 경우 정답을 제시해야합니다. POSIX 참조는 “Shell Command Language”장의“Simple Commands”입니다 .some-command
some-command
경우 some-command
입니다 외부 명령 , VAR=VALUE some-command
동일합니다 env VAR=VALUE some-command
. VAR
의 환경에서 내보내지고 some-command
셸의 값 (또는 값이 없음)은 변경되지 않습니다.
경우 some-command
A는 함수가 다음 VAR=VALUE some-command
에 해당합니다 VAR=VALUE; some-command
, 즉 장소에 할당 남아 함수 후가 돌아왔다, 그리고 변수는 환경에 내보낼 수 없습니다. 그 이유는 Bourne 쉘의 디자인과 관련이 있으며 그 이후에는 이전 버전과의 호환성과 관련이 있습니다. 함수 실행 주위에 변수 값을 저장하고 복원하는 기능이 없었습니다. 함수는 셸 자체에서 실행되므로 변수를 내 보내지 않는 것이 좋습니다. 그러나 ksh (ATT ksh93 및 pdksh / mksh 모두 포함), bash 및 zsh VAR
는 함수 실행 중에 만 설정되는 (내 보낸) 보다 유용한 동작을 구현합니다 . 에서는 KSH 함수가 KSH 구문으로 정의되는 경우,이 이루어진다function NAME …
표준 구문으로 정의 된 경우가 아닙니다 NAME ()
. 에서 bash는 (함께 실행할 때이되지 POSIX 모드에서 만 떠들썩한 파티 모드에서 이루어집니다 POSIXLY_CORRECT=1
). zsh 에서는 posix_builtins
옵션이 설정되지 않은 경우 수행됩니다 . 이 옵션은 기본적으로 설정되어 있지 않지만 emulate sh
또는 로 설정되어 emulate ksh
있습니다.
경우 some-command
내장 명령이 동작은 내장의 유형에 따라 달라집니다. 특수 내장 기능처럼 작동합니다. 특수 내장 기능은 상태 쉘에 영향을 미치기 때문에 쉘 내부에 구현되어야하는 것들입니다 (예 : break
제어 흐름, cd
현재 디렉토리, set
위치 매개 변수 및 옵션에 영향을 미칩니다). 다른 내장 기능 은 성능과 편의성을 위해 내장 되어 있으며 (예 : bash 기능 printf -v
은 내장 기능으로 만 구현할 수 있음) 외부 명령처럼 동작합니다.
할당은 경우에, 그래서 별칭 확장 후 발생 some-command
입니다 별칭 , 무슨 찾기 위해 먼저 확장합니다.
모든 경우에 명령 행 자체에 대한 변수 대체를 포함하여 명령 행을 구문 분석 한 후에 지정이 수행됩니다. 그래서 var=a; var=b echo $var
인쇄 a
때문에 $var
할당이 일어나기 전에 평가된다. 따라서 IFS=. printf "%s\n" $var
이전 IFS
값을 사용하여 분할 $var
합니다.
모든 유형의 명령을 다루었지만 한 가지 더 있습니다. 실행할 명령이없는 경우, 즉 명령이 할당 (및 가능한 재 지정)으로 만 구성된 경우입니다. 이 경우 과제는 그대로 유지됩니다 . VAR=VALUE OTHERVAR=OTHERVALUE
와 같습니다 VAR=VALUE; OTHERVAR=OTHERVALUE
. 따라서 이후 IFS=. arr=($var)
로 IFS
설정된 상태로 유지됩니다 .
. $IFS
과제에 arr
이미 새로운 가치가 있다고 기대할 수 있기 때문에 의 새로운 가치 IFS
가의 확장에 사용 된다는 것이 합리적 입니다 $var
.
요약하면, 당신은 사용할 수 있습니다 IFS
에 대한 일시적 전용 필드 분할 :
- 새로운 쉘 또는 서브 쉘을 시작함으로써 (예를 들어 , 값 이 2 자 미만인 경우 다르게 행동
third=$(IFS=.; set -f; set -- $var; echo "$3")
하는third=${var#*.*.}
것을 제외하고 는 복잡한 방법이다 );var
.
- ksh에서,
IFS=. some-function
여기서some-function
ksh 구문으로 정의됩니다function some-function …
. IFS=. some-function
호환성 모드가 아닌 기본 모드에서 작동 하는 한 bash 및 zsh에서 .
답변
@Gilles의 답변은 정말 훌륭합니다. 그는 복잡한 문제에 대해 자세히 설명합니다.
그러나이 명령에 대한 대답은 다음과 같습니다.
$ IFS=. printf "%s\n" $var
a.b.c
전체 명령 줄 이 실행 되기 전에 구문 분석 된다는 간단한 아이디어입니다 . 그리고 각 “단어”는 쉘에 의해 한 번 처리됩니다. 할당과 같은 , 지연됩니다 (4 단계가 마지막입니다) :IFS=.
각 변수 할당은 확장되어야한다.
명령이 실행되기 직전과 인수의 모든 확장이 먼저 처리되어이 실행 가능 라인을 빌드합니다.
$ IFS=. printf "%s\n" a.b.c ## IFS=. goes to the environment.
a.b.c
의 값 $var
에 “오래된”IFS와 확장 a.b.c
명령 전에이 printf
인수를 부여 "%s\n"
하고 a.b.c
.
평가
한 단계의 지연은 다음에 의해 도입 될 수 있습니다 eval
.
$ IFS=. eval printf "'%s\n'" \$var
a
b
c
줄이 구문 분석되고 (첫 번째) ‘IFS =.’ 다음과 같이 환경으로 설정됩니다.
$ printf '%s\n' $var
그런 다음 다시 이것으로 구문 분석됩니다.
$ printf '%s\n' a b c
그리고 이것을 실행 :
a
b
c
값 $var
(ABC)를 사용 IFS의 값으로 분할된다 : .
.
환경
복잡하고 까다로운 부분은 !!!
그것은 Gilles의 첫 번째 부분에서 잘 설명되어 있습니다.
추가 세부 사항이 있습니다.
이 명령이 실행될 때 :
$ IFS=. arr=($var)
IFS의 가치는 현재 환경에서 유지됩니다. 예 :
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <.>
단일 진술에 대한 IFS.
그러나 피할 수 있습니다 : 단일 명령문에 IFS 설정
$ IFS=. command eval arr\=\(\$var\)
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <
>
답변
귀하의 질문
var=a.b.c
IFS=. printf "%s\n" $var
코너 케이스입니다.
쉘 변수 가 설정 되기 전에macro expansion
명령에서 in이 발생 하기 때문 IFS=.
입니다.
즉 $var
, 확장되면 이전 IFS
값이 활성화되고로 IFS
설정됩니다 '.'
.