수색…


비고

중괄호로 묶인 표현식 문자열 사용의 또 다른 이점은 바이트 컴파일러가 대개보다 효율적인 코드 (5 - 10 배 빠름)를 생성 할 수 있다는 것입니다.

칭찬을받지 않은 표현의 문제점

표현 문자열 인수를 괄호로 묶은 문자열로 제공하는 것이 좋습니다. "Double Substitution"이라는 제목은 같은 이유로 중요한 이유를 설명합니다.

expr 명령은 연산자 기반의 표현식 문자열을 평가하여 값을 계산합니다. 이 문자열은 호출의 인수로 구성됩니다.

expr 1 + 2    ; # three arguments
expr "1 + 2"  ; # one argument
expr {1 + 2}  ; # one argument

이 세 가지 호출은 동일하며 표현식 문자열은 동일합니다.

if , forwhile 명령은 조건 인수에 대해 동일한 평가 기 코드를 사용합니다.

if {$x > 0} ...
for ... {$x > 0} ... ...
while {$x > 0} ...

가장 큰 차이점은 조건식 문자열이 항상 하나의 인수 여야한다는 것입니다.

Tcl에서 명령 호출의 모든 인수와 마찬가지로 내용은 인용 / 이스케이프 된 방법에 따라 대체 대상이 될 수도 있고 그렇지 않을 수도 있습니다.

set a 1
set b 2
expr $a + $b   ; # expression string is {1 + 2}
expr "$a + $b" ; # expression string is {1 + 2}
expr \$a + \$b ; # expression string is {$a + $b}
expr {$a + $b} ; # expression string is {$a + $b}

백 슬래시 / 중괄호가 대체를 방지하므로 세 번째 및 네 번째 경우에 차이가 있습니다. expr 내부의 평가자는 Tcl 변수 대체를 수행하고 문자열을 {1 + 2} 로 변환 할 수 있으므로 결과는 여전히 동일합니다.

set a 1
set b "+ 2"
expr $a $b   ; # expression string is {1 + 2}
expr "$a $b" ; # expression string is {1 + 2}
expr {$a $b} ; # expression string is {$a $b}: FAIL!

expr 의 평가자가 대체를 수행 할 때 표현식 문자열이 이미 연산자와 피연산자로 구문 분석되었으므로 평가자는 두 연산자 사이에 연산자가없는 두 개의 피연산자로 구성된 문자열을 인식합니다. 오류 메시지는 " missing operator at _@_ in expression "$a _@_$b" " missing operator at _@_ in expression "$a _@_$b"missing operator at _@_ in expression "$a _@_$b" .

이 경우 expr 이 호출되기 전의 변수 대체가 오류를 방지합니다. 인수를 사용하면 표현식 평가 때까지 변수 대체가 금지되어 오류가 발생했습니다.

이와 같은 상황은 가장 일반적으로 평가할 표현식이 변수 또는 매개 변수로 전달 될 때 발생할 수 있습니다. 이 경우 인수 평가자가 expr 에 전달할 표현식 문자열을 "압축 해제"할 수 있도록 인수를 비방 검정으로 두는 것 외에 다른 선택은 없습니다.

그러나 대부분의 다른 경우에는 표현을 지키지 않아도 아무런 해가 없으며 실제로 많은 문제를 피할 수 있습니다. 이에 대한 몇 가지 예 :

이중 치환

set a {[exec make computer go boom]}
expr $a      ; # expression string is {[exec make computer go boom]}
expr {$a}    ; # expression string is {$a}

unbraced 형식은 명령 대체를 수행합니다. 명령 대체는 컴퓨터를 어떻게 든 파괴합니다 (또는 하드 디스크를 암호화하거나 포맷하거나 명령을 내리는 것). braced 형식은 변수 대체를 수행 한 다음 문자열 "[exec make computer go boom]"을 만들기 위해 시도하고 실패합니다. 재해가 막혔습니다.

끝없는 루프

set i 10
while "$i > 0" {puts [incr i -1]}

이 문제는 forwhile 모두 영향을 미칩니다. 이 루프가 0으로 카운트 다운되고 종료되는 것처럼 보이지만 while에 대한 조건 인수는 while 명령이 활성화되었을 때 인수가 평가 된 것이기 때문에 실제로 항상 10>0 입니다. 인수가 괄호로 묶여 있으면 while 명령에 $i>0 으로 전달되고 반복 될 때마다 변수가 한 번 대체됩니다. 이것을 대신 사용하십시오 :

while {$i > 0} {puts [incr i -1]}

종합 평가

set a 1
if "$a == 0 && [incr a]" {puts abc}

이 코드를 실행 aa 의 값은 무엇입니까? && 연산자는 왼쪽 피연산자가 참인 경우에만 오른쪽 피연산자를 평가하므로 값은 여전히 ​​1이어야합니다. 그러나 실제로는 2입니다. 이는 인수 평가 기가 표현식 문자열이있는 시간까지 모든 변수 및 명령 대체를 이미 수행했기 때문입니다 평가. 이것을 대신 사용하십시오 :

if {$a == 0 && [incr a]} {puts abc}

여러 연산자 (논리 ||&& 및 조건부 연산자 ?: :)는 모든 피연산자를 평가 하지 않도록 정의되지만 표현식 문자열이 괄호로 묶여있는 경우에만 설계대로 작동 할 수 있습니다.

변수에 17을 곱한다.

set myVariable [expr { $myVariable * 17 }]

간단한 표현식을 사용하여 변수를 업데이트하는 방법을 보여줍니다. expr 명령은 변수를 업데이트하지 않습니다. 그 결과를 가져 와서 set 을 사용하여 변수에 써야합니다.

newline은 expr 이해하는 작은 언어에서는 중요하지 않으며, 더하기 표현을 사용하면 더 긴 표현식을 훨씬 쉽게 읽을 수 있습니다.

set myVariable [expr {
    $myVariable * 17
}]

이것은 정확히 똑같은 일을합니다.

표현식에서 Tcl 명령 호출

때로는 표현식에서 Tcl 명령을 호출해야 할 때도 있습니다. 예를 들어 문자열 길이가 필요하다고 가정합니다. 그렇게하기 위해, 당신은 단지 표현식에서 [...] 시퀀스를 사용합니다 :

set halfTheStringLength [expr { [string length $theString] / 2 }]

이 방법으로 Tcl 명령을 호출 할 수는 있지만, 스스로 expr 호출하면 멈추십시오! 그 여분의 전화가 정말로 필요한지 생각해보십시오. 대개 내부 표현식을 괄호 안에 넣으면됩니다.

잘못된 bareword 오류

Tcl 자체에서 한 단어로 구성된 문자열은 따옴표로 묶을 필요가 없습니다. expr 평가하는 표현식 문자열의 언어에서 모든 피연산자는 식별 가능한 유형을 가져야합니다.

숫자 피연산자는 장식없이 작성됩니다.

expr {455682 / 1.96e4}

부울 상수는 다음과 같습니다.

expr {true && !false}

Tcl 변수 대체 구문이 인식됩니다. 피연산자가 변수의 값으로 설정됩니다.

expr {2 * $alpha}

명령 대체도 마찬가지입니다.

expr {[llength $alpha] > 0}

피연산자는 괄호 안에 피연산자를 쉼표로 구분하여 나열한 수학 함수 호출 일 수도 있습니다.

expr {sin($alpha)}

피연산자는 큰 따옴표 또는 중괄호 문자열 일 수 있습니다. 큰 따옴표로 묶인 문자열은 명령 줄 에서처럼 대체 할 수 있습니다.

expr {"abc" < {def}}

피연산자가 위와 같지 않으면 불법입니다. 어떤 종류의 단어인지를 보여주는 힌트가 없으므로 expr 은 bareword 오류를 표시합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow