나는 "목록 컨텍스트"와 "문자열 컨텍스트"가 여러 번 사용되는 것을 보았습니다.
나는 Perl에서 그러한 설명의 사용을 알고 이해합니다. 그들을$ 및 @에 적용됩니다..
그러나 쉘 설명에 사용되는 경우:
- 쉘 구문에는 목록 컨텍스트와 문자열 컨텍스트라는 두 가지 컨텍스트가 있습니다.
- 따옴표 누락(목록 컨텍스트에서)
- 모든 목록 컨텍스트에서 변수 주위에는 항상 따옴표가 필요합니다.
- 목록 컨텍스트에서 인용되지 않은 변수를 유지합니다(echo $var에서와 같이).
이는 어디에도 정의되지 않거나 기껏해야 잘 문서화되지 않은 분산된 용어인 것처럼 보입니다 .
POSIX에는 이에 대한 정의가 없습니다.구글에 따르면
이것은(따라서) 그것의 요점은 무엇입니까? :
즉, 단어 목록이나 패턴이 필요할 때마다 큰따옴표가 필요합니다. 파서가 원시 문자열을 요구하는 상황에서는 선택 사항입니다.
하지만 이 용어는 사용하기 어려운 것 같습니다. 문자열 컨텍스트인지 목록 컨텍스트인지 확인하기 위해 "결과가 필요"할 때 "결과가 무엇이어야 하는지"를 어떻게 찾을 수 있습니까?
아니면 정확하고 정확하게 정의할 수 있습니까?
답변1
표준 쉘 언어에는 그러한 개념이 없습니다. "컨텍스트"는 없으며 단지 단계를 확장하는 것뿐입니다.
따옴표는 생성된 단어의 토큰화에서 먼저 인식됩니다. 그들은 단어를 서로 붙여 abc"spaces here"xyz
"단어"를 형성합니다 .
이해해야 할 중요한 점은 인용문이 후속 확장 단계에서 보존되며 원래 인용문은 확장에 나타날 수 있는 인용문과 구별된다는 것입니다.
매개변수 확장에서는 큰따옴표를 고려하지 않습니다. 그러나 필드 분할 프로세스는 나중에 발생하며 이는 첫 번째 토큰화로 다시 이어집니다. 따옴표는 다시 분할을 방지하고 다시 유지됩니다.
이 분할 후에 경로 이름 확장("globbing")이 발생합니다. 유지된 따옴표는 이를 방지합니다. 와일드카드 연산자는 따옴표 내에서 인식되지 않습니다.
마지막으로 "인용 제거"라는 이후 단계에서 따옴표가 제거됩니다. 물론, 단지원래인용 부호!
POSIX는 잘한다도입과정이해할 수 있는 방식으로, 관련 없는 개념(오해의 소지가 있음)으로 신비를 풀려고 하면 이해가 혼란스러울 뿐입니다.
쓰레기를 버리는 사람들애드 혹"목록 컨텍스트"와 같은 개념은 모든 처리에 대해 동등한(동일한 결과를 생성하는) 완전한 대체 사양을 제공할 수 있도록 아이디어를 공식화해야 합니다. 그런 다음 병렬 설계 간에 개념을 혼합하지 마십시오. 한 가지 해석을 사용하십시오. "목록 컨텍스트" 또는 "문자열 컨텍스트"는 이러한 개념이 잘 정의되고 처리 단계가 이를 중심으로 구성되는 쉘 확장 이론에서 의미가 있습니다.
추측하자면 "목록 컨텍스트"는 쉘이 토큰화된 단어 목록(예: 두 단어 목록)을 처리한다는 아이디어를 나타냅니다 {foo} {abc" x "def}
. 따옴표는 두 번째 단어의 일부가 아닙니다. 그 내용은 실제로 abc x def
공백 분할을 방지하는 의미론적 따옴표입니다. 이 따옴표 안에는 "문자열 컨텍스트"가 있습니다.
그러나 이러한 확장 단계를 구현하는 것은 불가능합니다.실제로원시 인용으로 식별되는 인용도 있지만 일종의 목록 데이터 구조, 즉 {foo} {abc" x "def}
인용된 부분이 다른 유형의 노드로 식별되는(그리고 인용이 사라지는) 목록의 목록입니다. Lisp 표기법을 사용하면 다음과 같을 수 있습니다.
(("foo") ;; one-element word
("abc" (:dq-str " x ") "def")) ;; three-element word
:dq-str
레이블이 없는 노드는 큰따옴표로 묶인 영역인 리터럴 텍스트입니다 . :sq-str
단일 참조 항목에는 다른 유형을 사용할 수 있습니다 .
확장은 이 구조를 반복하고 :dq-str
문자열 개체, 표현식 또는 기타 항목을 보고 있는지 여부에 따라 다양한 작업을 수행할 수 있습니다. :dq-str
또는 에서는 파일 확장자와 필드 분할이 억제됩니다 :sq-str
. 하지만 매개변수 확장하다내에서 발생합니다 :dq-str
. "참조 제거"는 조각을 가져와 문자열을 연결하고 내부 목록 구조를 평면화하고 유형 표시기를 잃는 최종 패스에 해당하며 결과는 다음과 같습니다.
("foo"
"abc x def") ;; plain string list, usable as command arguments
이제 두 번째 항목에는 ("abc" (:dq-str " x ") "def")
첫 번째 항목과 마지막 항목이 확장되어 있습니다. 해당 항목은 목록의 직접 요소이므로 "목록 컨텍스트"에 있다고 말할 수 있습니다. 그리고 중간에 있는 내용은 표현식, 즉 "(큰따옴표) 문자열 컨텍스트" " x "
로 래핑됩니다 .:dq-str
"목록 컨텍스트"에서 "목록"이 의미하는 것은 이와 같이 명확하게 정의된 모델이 없으면 누구나 추측할 수 있는 것입니다. 주요 단어 목록인가요? 아니면 단어를 나타내는 덩어리 목록인가요?
답변2
당신이 인용한 사건의 대부분이 나에게 일어났기 때문에 @Gilles의 말을 대부분 의역하겠지만 여기에 답을 주어야 할 것 같습니다.
나는 사용해왔다목록 컨텍스트그리고스칼라/비목록 컨텍스트(비교하다문자열 컨텍스트적어도 2004년 이후에는 비목록 컨텍스트로 이해되지 않으면 수십 번 혼란을 야기할 수 있습니다.존재하다뉴스 네트워크또는UNIXSE대부분의 시간은 Bourne과 같은 쉘에서 확장을 인용하지 않는 것의 효과를 논의하는 기사에 할애되었습니다. 이전에 내가 의미했던 바를 명확히 해달라고 요청한 사람이 기억나지 않습니다.종종 이러한 유형의 배경에 대한 몇 가지 예를 들어 설명해 보십시오.)
나는 이것을 쉘 언어의 공식적인 사양에서 사용하지 않고 단지 다른 사람들에게 쉘 동작을 설명하는 데 도움이 되는 영어 텍스트일 뿐입니다.
그건 아니야공식 용어이는 분명히 perl
공식(문서의) 용어에서 영감을 받은 것입니다. 나보다 먼저 Unix 쉘 환경에서 이것을 사용한 사람이 있는지는 알 수 없지만(아마도 그랬을 것입니다), 그 이후로 사용한 사람은 분명 있습니다. 나는 그것을 소유한다고 주장하지 않습니다.
목록 컨텍스트(적어도 그것이 사용되는 컨텍스트에서 사용할 때) 단지 쉘이 컨텍스트에서 임의의 수의 요소를 기대한다는 것을 의미합니다. 하지만스칼라/비목록/문자열 컨텍스트perl
대부분의 Bourne 유사 쉘에서 이러한 목록 컨텍스트는 다음 과 같습니다.
- 간단한 명령 매개변수(예:)
echo elements
for i in elements
array=(elements)
(및 변형+=
)
일부 쉘에는 다음과 같은 기능이 더 있습니다.
cmd < elements
zsh
(예: 그러나)와 유사한 작업을 수행합니다 .cat -- elements | cmd
nl < *.txt
nl < {foo,bar}.txt
nl < foo.txt < bar.txt
cmd > elements
(및>|
>>
...의 변형)zsh
다음과 같은 작업을 수행합니다.cmd | tee -- elements
elements() { code; }
zsh
한 번에 하나 이상의 기능을 정의합니다(또는 다음과 같은 경우요소빈 목록으로 구문 분석합니다(리터럴() { echo x; }
은익명 함수)).compound=(foo=(elements) elements)
아니면 등등.matrix=((elements) (elements))
ksh93
- 등.
이러한 경우 glob은 일반적으로 확장되며, 분할+glob을 적용하지 않으려면 확장을 참조해야 합니다 (또는 /sh 호환성 옵션을 zsh
활성화하지 않는 한 null을 제거하기만 하면 됩니다).shwordsplit
globsubst
예를 들어 교체하면요소*.txt
위의 예 에서는 *.txt
현재 디렉터리의 txt 파일 목록이 확장됩니다.
POSIX 사양에서 이에 상응하는 항목을 찾고 있다면 glob이 확장되는 컨텍스트를 찾으세요. POSIX, 적어도 하나의 인스턴스에서는 이를 호출합니다.필드 분할이 수행되는 컨텍스트(실제로는 이후에 문구가 변경되었습니다.이전 문구에 대해 오스틴 그룹에 문제를 제기했습니다.). 물론, 이 표현은 다음과 같은 질문에 대답하는 데 그다지 유용하지 않습니다.필드 분할을 수행할 위치.
이것스칼라 컨텍스트다른 맥락일 것이다.
존재하다
scalar=*.txt
case *.txt in...
[[ -f *.txt ]]
*.txt
쉘은 단지 예상하기 때문에 확장할 수 없습니다하나끈.
cmd > *
경고/제한 사항으로 이러한 용어는 / (POSIX 모드가 아닌 경우), (구문 대신 사용) 또는 (일부와 상호 작용하는 경우에만)와 같이 셸에서 발생하는 일을 명확하게 포착하지 않습니다. 또 다른cmd > ~(N)pattern
a=(); b=; c=(a b); d=*; IFS=:; e=a:b; cmd 1> "${a[@]}" 2> $b 3> "${c[@]}" 4> $d 5> $e
bash
yash
ksh88
set -A
var=(...)
ksh93
목록 컨텍스트단 하나의 요소를 포함하는 목록만 필요합니다(분할 및 와일드카드는 경우에 따라 다르게 작동함).
답변3
이것말씨"목록 컨텍스트"와 "문자열 컨텍스트"는 Perl에서 유래했지만 유사한 개념이 쉘 언어에도 적용됩니다. 참고하시기 바랍니다비슷한개념: 컨텍스트의 종류와 컨텍스트 유형에 따른 결과가 다릅니다.
이 단어문맥프로그래밍 언어의 의미에 관한 기술 용어입니다. 그것은정밀한의미는 이 답변의 범위를 벗어나는 의미론의 특정 형식화와 연결되어 있습니다. 이것인식의미는 코드를 둘러싼 환경의 특성입니다. 예를 들어, 코드 조각이 $foo
서로 다른 상황에서 서로 다른 의미를 갖는다는 것은 포함된 프로그램의 동작이 프로그램에 나타나는 내용의 특성 $foo
에 따라 달라진다는 것을 의미합니다.$foo
쉘의 의미는 매우 복잡합니다. 이는 프로그래밍 언어 입문 교과서의 전통적인 범주에 맞지 않습니다. 쉘 프로그램의 실행은 두 단계로 나눌 수 있습니다. (이것은 의미를 표현하는 방법이지 쉘 인터프리터가 이를 이런 방식으로 나누어야 한다는 의미는 아닙니다.)
구문 분석 단계에서는 문자열(소스 파일의 내용 또는 매개변수의 내용
-c
)을 추상 구문 트리로 변환합니다. 내부에POSIX 사양, 이는 2단계와 3단계(마커 식별 및 구문 분석)에 해당합니다. POSIX 사양 정의문법 규칙나무의 모양을 묘사해 보세요. 이것은 문맥 자유 문법이 아니라는 점에 유의하십시오. 데모는 문맥 자유 문법의 일반적인 시연을 기반으로 하지만 "규칙 적용"이라는 설명이 있습니다.질소” 이를 더욱 복잡한 수학적 객체로 만듭니다.실행 단계에서는 트리 노드에 대한 일부 평가를 수행하고 외부 명령을 호출합니다. POSIX 사양에서 이는 4~7단계(확장, 리디렉션, 명령 실행 및 대기)에 해당합니다.
확장WORD
POSIX가 "단어" 라고 부르는 추상 구문 트리의 특정 유형의 노드에 적용되는 프로세스입니다 . 두 그룹으로 나눌 수 있습니다.
POSIX 용어에서 첫 번째 확장 세트에는 다음이 포함됩니다.물결표 확장(예:
~foo
→/home/foo
),매개변수 확장(예를 들어$foo
→bar
값이 다음과 같은 경우),foo
bar
명령 대체(예:$(foo)
→bar
명령 출력이 다음과 같은 경우foo
)bar
및산술 확장(예:$((2+2))
→4
). 첫 번째 확장 세트는 작은따옴표 안에 있거나 백슬래시가 앞에 있어서 "따옴표"로 묶인 문자를 제외한 모든 단어에 대해 수행됩니다. 이 확장 세트의 출력은 대략 주석이 달린 문자열입니다(대략적인 내용은 아래에서 설명하겠습니다).두 번째 확장 세트에는 다음이 포함됩니다.필드 분할그리고경로명 확장(종종 "파일 이름 생성" 또는 "와일드카드 지정"이라고 함) 이 확장 세트는 주석이 달린 문자열을 문자열 목록으로 변환합니다. 이 확장 세트는 첫 번째 세트가 수행되는 위치의 하위 세트에서 수행됩니다. 큰따옴표로 묶인 단어 부분에서는 수행되지 않습니다.단어가 추상 구문 트리 어딘가에 있으면 전혀 실행되지 않습니다.. 이것이 목록 및 문자열 컨텍스트가 들어오는 곳입니다. 특정 컨텍스트, 즉 추상 구문 트리의 특정 위치 범주에 대해 두 번째 확장 집합이 수행됩니다. 이것들은 모두목록 컨텍스트, 확장 프로세스의 결과가 (문자열) 목록이기 때문에 그렇게 명명되었습니다. 다른 경우에는 다음과 같이 불린다.문자열 컨텍스트, 두 번째 확장 세트는 수행되지 않으며 확장 프로세스의 결과는 단일 문자열입니다.
POSIX 설명견적 삭제마지막 확장 단계와 같습니다. 이는 참조를 해석하는 한 가지 방법이며, 필드 분할 전의 모든 확장은 문자열에서 문자열로의 변환으로 정의됩니다. 예를 들어, 단어가 주어지고 '$foo'$bar\$qux
변수의 값이 이라고 가정하면 bar
매개 value
변수 확장은 이를 로 변환하는 '$foo'value\$qux
반면, 다른 첫 번째 확장 세트는 문자열을 변경하지 않고 그대로 둡니다. 견적 제거 마지막으로 견적을 제거하여 $foovalue$qux
.
따옴표 제거 데모에서는 모든 단계에서 따옴표 일치를 수행해야 합니다. 더 쉽게 따르고 구현하고 동일한 최종 결과를 제공하는 데모는 부품 목록을 생성하는 역참조 단계를 수행하는 것입니다. 각 섹션에는 참조 여부를 기억하기 위해 주석이 달려 있습니다. 예를 들어, quoted , unquoted 변수 확장 , quoted , naked , naked , naked 를 '$foo'$bar\$qux
역따옴표로 표시하세요 . (할당 식별 및 별칭 확장 여부 결정과 같은 작업에는 "참조"와 "네이키드"를 구별하는 것이 필요합니다.) 2단계 확장은 목록 컨텍스트의 참조되지 않은 부분에서만 발생합니다.$foo
bar
$
q
u
x
POSIX는 확장 단계를 명시적으로 나열하여 두 번째 확장 세트가 발생하는지 여부를 지정합니다. 예를 들어, "모든 변수 할당은 값을 할당하기 전에 물결표 확장, 매개변수 확장, 명령 대체, 산술 확장 및 따옴표 제거를 거쳐야 합니다." 이를 더 간단하게 설명하면 첫 번째 확장 세트만 발생한다는 것입니다. 즉 할당은 문자열 컨텍스트입니다. 확장 실행을 위한 규칙 세트가 두 개뿐이므로 컨텍스트도 두 개만 있습니다. 즉, 첫 번째 세트의 모든 규칙이 실행되거나(문자열 컨텍스트) 두 세트가 모두 순차적으로 실행됩니다(목록 컨텍스트).
case
(실제로 완전성을 기하기 위해 세 번째 종류의 컨텍스트인 패턴 컨텍스트가 있습니다 . case
패턴에서는 첫 번째 확장 세트만 수행되지만(문자열 컨텍스트에서와 마찬가지로) 두 번째 확장 세트의 일부는 다음과 같습니다. 관련 - 따옴표가 없는 와일드카드 문자는 문자열 일치를 위한 와일드카드 문자입니다.
언어 정의는 어떤 컨텍스트가 목록 컨텍스트이고 어떤 컨텍스트가 문자열 컨텍스트인지를 지정합니다. 원칙적으로 이는 임의적일 수 있습니다. 그러나 그 뒤에는 직관이 있습니다. 문법에 토큰 목록이 필요한 경우 WORD
해당 토큰에 대해 두 번째 확장 집합이 수행되고, 문법에 단일 목록이 필요한 경우 WORD
두 번째 확장 집합이 수행되지 않습니다. 이를 설명하는 간단한 방법은 문법에 목록이 필요한 경우 목록 컨텍스트이고, 문법에 단일 문자열이 필요한 경우 문자열 컨텍스트라는 것입니다.