필드 분할에 임시 IFS를 언제 사용할 수 있습니까? 섹션을 빠르게 읽 더라도 어느 쪽도 지시하지

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-commandsome-command

경우 some-command입니다 외부 명령 , VAR=VALUE some-command동일합니다 env VAR=VALUE some-command. VAR의 환경에서 내보내지고 some-command셸의 값 (또는 값이 없음)은 변경되지 않습니다.

경우 some-commandA는 함수가 다음 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-functionksh 구문으로 정의됩니다 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설정됩니다 '.'.