분사란 무엇입니까? 쉘 프로그래밍에서 이것이 왜 중요한가요?

분사란 무엇입니까? 쉘 프로그래밍에서 이것이 왜 중요한가요?

에서 분사의 역할이 혼란스럽습니다 zsh. 저는 C, Python 또는 MATLAB으로 프로그래밍하는 동안 이 개념을 접한 적이 없었으며 이로 인해 단어 분할이 쉘 프로그래밍에 고유한 것처럼 보이는 이유에 대한 관심이 촉발되었습니다.

이전에 이 사이트와 다른 사이트에서 단어 분할에 대해 읽었지만 개념에 대한 명확한 설명을 찾지 못했습니다. 위키피디아에는 하나가 있습니다.분사의 정의그러나 이것이 Unix 쉘에 어떻게 적용되는지에 대한 언급은 없는 것 같습니다.

내 혼란의 예는 다음과 같습니다 zsh.

내부에Z 쉘 FAQ, 나는 다음을 읽었습니다.

3.1: 왜 내 기대에 미치지 못하는 $var곳이 있나요?var="foo bar"

대부분의 Bourne-shell 파생 항목에서 다중 단어 변수(예:)는 var="foo bar" 명령에 전달되거나 루프에서 사용될 때 단어로 분할됩니다 for foo in $var. 기본적으로 zsh에는 이러한 동작이 없습니다. 변수는 변경되지 않은 상태로 유지됩니다. (이것은 오류가 아닙니다! 아래를 참조하십시오.) 이 옵션은 SH_WORD_SPLIT호환성을 위해 존재합니다.

하지만,Z Shell 매뉴얼에서, 나는 다음을 읽었습니다.

SH_WORD_SPLIT (-y) <K> <S>

따옴표가 없는 매개변수 확장 시 필드 분할이 수행됩니다. 이 옵션에 주목하세요할 것이 없다 분사로. (매개변수 확장을 참조하세요.)

SH_WORD_SPLIT왜 있다고 하는데?할 것이 없다분사로? 이건 분사 아닌가요?

답변1

초기 쉘에는 문자열이라는 단 하나의 데이터 유형만 있었습니다. 그러나 일반적으로 여러 파일 이름을 프로그램에 인수로 전달할 때 문자열 목록을 조작하는 것은 매우 일반적입니다. 분할의 또 다른 일반적인 사용 사례는 명령이 결과 목록을 출력하는 경우입니다. 명령의 출력은 문자열이지만 필요한 데이터는 문자열 목록입니다. 변수에 파일 이름 목록을 저장하려면 이름 사이에 공백을 추가하면 됩니다. 그런 다음 이와 같은 쉘 스크립트

files="foo bar qux"
myprogram $files

myprogram쉘이 문자열을 단어로 분할할 때 $files세 개의 인수로 호출됩니다 . 당시 파일 이름의 공백은 금지되었거나 미완성으로 널리 간주되었습니다.

이것코헨 쉘배열 소개: 문자열 목록을 변수에 저장할 수 있습니다. Korn 쉘은 당시 확립된 Bourne 쉘과 여전히 호환되므로 기본 변수 확장은 지속적인 토큰화를 수행하고 배열을 사용하려면 약간의 구문 오버헤드가 필요합니다. 위의 스니펫을 작성할 수 있습니다.

files=(foo bar qux)
myprogram "${files[@]}"

Zsh는 처음부터 배열을 가지고 있었고 작성자는 이전 버전과의 호환성을 희생하면서 더 합리적인 언어 디자인을 선택했습니다. zsh에서는(기본 확장 규칙에 따라) $var단어 분리가 수행되지 않습니다. 단어 목록을 변수에 저장하려면 배열을 사용해야 합니다 $=var.

files=(foo bar qux)
myprogram $files

파일 이름의 공백은 요즘 처리해야 할 문제입니다. 많은 사용자가 공백이 작동할 것으로 기대하고 공격자가 잠재적으로 파일 이름을 제어할 수 있는 보안에 민감한 컨텍스트에서 많은 스크립트가 실행되기 때문입니다. 따라서 자동 단어 분리는 종종 문제가 됩니다. 따라서 일반적인 조언은 "$foo"특정 사용 사례에서 단어 분리가 필요한 이유를 이해하지 않는 한 항상 큰따옴표를 사용하는 것입니다 . (기본 변수 확장에도 와일드카드가 발생한다는 점에 유의하세요.)

내 대답에서 나는 "분사"라는 단어를 사용했습니다. 변수를 설정하여 단어(필드라고도 함)의 구성을 구성할 수 있기 때문에 이를 "필드 분할"이라고도 합니다 IFS. 단어 안의 모든 문자는 IFS단어 구분 기호로 간주되며 단어는 단어가 아닌 일련의 문자입니다. 분리 기호. 기본적으로 IFS기본 공백 문자가 포함됩니다(캐리지 리턴, 분할할 수 없는 공백 등이 아닌 ASCII 공백, 탭 및 줄 바꿈). zsh 매뉴얼에서는 "단어 분리"를 쉘 코드 구문 분석 단계를 참조하기 위해서만 사용하며, 변수 및 명령 대체 후에 발생하는 확장의 일부인 필드/단어 분할과는 아무런 관련이 없습니다.

답변2

Zsh의 특정 사례에서 단어 분할은 필드 분할과 약간 다르게 정의됩니다.

생각해 보세요 prog a b c. 어떻게 설정하든 세 개의 매개변수를 전달합니다 IFS. 이것은단어나뉘다.

이 작업이 완료되면 공백이 포함되어 있으면 세 개의 인수를 전달하고 그렇지 않으면 하나의 인수를 전달 A="a b c"; prog $A합니다 . IFS이것은대지나뉘다.

여기서의 정의는 미묘합니다. Zsh 문서에서 말하려는 것은 옵션을 비활성화하더라도 prog a b c여전히 별도의 인수를 얻게 된다는 것입니다(이는 항상 예상되는 것입니다).

답변3

토큰화는 실제로 쉘에만 국한되지 않습니다.

텍스트 입력을 구문 분석해야 하는 대부분의 프로그램은 첫 번째 단계로 일종의 토큰화를 사용합니다. 이는 숫자, 연산자, 문자열, 토큰 및 이러한 "단어"에서 처리해야 하는 유사한 엔터티를 식별하기 전에 수행됩니다.

쉘은 공백이 포함된 인수 전달, 빈 인수, 사용자 정의 구분 기호 등을 포함하여 (C argc/argv, python sys.argv)라는 명령에 대한 인수 목록을 올바르게 구성해야 한다는 점에서 구체적입니다. 많은 쉘은 유연성을 제공하기 위해 IFS 변수를 사용합니다.

관련 정보