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


16

에서 단어 분리의 역할에 대해 혼란스러워지고 zsh있습니다. C, Python 또는 MATLAB으로 프로그래밍 할 때이 개념에 노출되지 않았으므로 이것이 단어 분할이 쉘 프로그래밍에 특정한 것으로 보이는 이유에 대한 관심을 불러 일으켰습니다.

이전에이 사이트와 다른 사이트에서 단어 분리에 대해 읽었지만 개념에 대한 명확한 설명을 찾지 못했습니다. Wikipedia에는 단어 분리에 대한 정의가 있지만 Unix 쉘에 어떻게 적용되는지에 대한 언급이없는 것 같습니다.

다음은 제가 혼동하는 예입니다 zsh.

에서 Z 쉘 자주 묻는 질문 , 나는 다음을 읽어

3.1 : 왜 않는 $var곳에 var="foo bar"내가 기대하지?

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

그러나 Z Shell Manual 에서 다음을 읽습니다.

SH_WORD_SPLIT (-y) <K> <S>

인용되지 않은 매개 변수 확장에서 필드 분할이 수행되도록합니다. 이 옵션 단어 분리와 관련이 없습니다 . (파라미터 확장 참조)

단어 분리와 관련SH_WORD_SPLIT없는 이유는 무엇 입니까? 이것이 무엇에 관한 것인지 정확하게 단어 분리하지 않습니까?

답변:


21

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

files="foo bar qux"
myprogram $files

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

Korn 쉘 배열을 소개 : 당신이 변수에 문자열 목록을 저장할 수 있습니다. Korn 쉘은 당시에 확립 된 Bourne 쉘과 호환 가능하므로 베어 변수 확장은 계속해서 단어 분할을 거쳤으며 배열을 사용하면 약간의 구문 오버 헤드가 필요했습니다. 위의 스 니펫을 작성합니다

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

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

files=(foo bar qux)
myprogram $files

요즘 파일 이름의 공백은 많은 사용자가 작업 할 것으로 예상하고 공격자가 파일 이름을 제어 할 수있는 보안에 민감한 컨텍스트에서 많은 스크립트가 실행되기 때문에 대처해야 할 부분입니다. 따라서 자동 단어 분리는 종종 성가신 일입니다. 따라서 "$foo"특정 유스 케이스에서 단어 분리가 필요한 이유를 이해하지 않는 한 항상 큰 따옴표, 즉 write를 사용하는 일반적인 조언이 있습니다. (가변 변수 확장은 globbing도 수행합니다.)


고마워 질, 이것은 정말 도움이됩니다! 대략 말로 단어를 나누면 양식의 문자열이 양식의 "word1 word2 word3"목록 / 배열로 변환된다고 말하는 것이 맞 "word1" "word2" "word3"습니까? 또한 zsh에서 특정 혼란 소스로 OP를 업데이트했습니다.
Amelio Vazquez-Reina

1
@intrpc "단어 분할"은 자연어 단어가 아니라 $IFS문자 로 분할됩니다 . 따라서 "필드 분할"이 더 나은 이름입니다. 그러나 "단어 분리"는 종종 쉘 문학에서이 개념에 사용됩니다. zsh 문서는 단어에 문제가 있습니다.
Gilles 'SO- 악의를 멈춰라'

1
rc변수 및 배열과 관련하여 zsh보다 더 나은 디자인은 plan9 쉘 (Unix로 포팅)도 참조하십시오 .
Stéphane Chazelas

3

단어 분리는 실제로 쉘에 한정되지 않습니다.

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

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


3

이 Zsh의 경우, 단어 분할은 필드 분할과 약간 다르게 정의됩니다.

고려 prog a b c는 상관없이 설정하는 방법 세 가지 인수를 전달하지 않습니다, IFS. 이것은 단어입니다 분리입니다.

그렇게 A="a b c"; prog $A하면 IFS공백 이 포함 된 경우 세 개의 인수가 전달되고 그렇지 않으면 하나의 인수가 전달됩니다. 이 필드입니다 분할입니다.

여기의 정의는 미묘합니다. Zsh 문서가 말하려는 것은 해당 옵션을 비활성화하더라도 prog a b c여전히 사람들이 항상 기대하는 별도의 인수를 얻게된다는 것입니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.