subst — 백슬래시·명령·변수 치환 수행하기
subst — 백슬래시·명령·변수 치환 수행하기
Tcl에서 $var나 [명령], \n 같은 치환이 어떻게 일어나는지 직접 조절하고 싶을 때가 있어요. subst는 문자열 인자에 변수 치환, 명령 치환, 백슬래시 치환을 수행하고 그 결과를 완전히 치환된 상태로 돌려주는 명령이에요.
본문
subst ?-nobackslashes? ?-nocommands? ?-novariables? string
이 명령은 string 인자에 변수 치환, 명령 치환, 백슬래시 치환을 수행해 완전히 치환된 결과를 돌려줘요. 치환 방식은 Tcl 명령에서 일어나는 것과 정확히 같아요. 그 결과 string 인자는 실제로 두 번 치환되는 셈이에요. 한 번은 Tcl 명령에서 평소처럼 파서가 처리하고, 다시 한 번 subst 명령이 처리하죠.
-nobackslashes, -nocommands, -novariables 중 아무거나 지정하면 해당 치환만 수행하지 않아요. 예를 들어 -nocommands를 지정하면 명령 치환이 일어나지 않아서 여는/닫는 대괄호가 특별한 의미 없는 평범한 문자로 취급돼요.
한 종류의 치환이 다른 종류의 치환을 포함할 수 있다는 점을 기억하세요. 예를 들어 -novariables 옵션을 지정해도 명령 치환은 제한 없이 수행돼요. 즉, 명령 치환을 완성하는 데 필요한 변수 치환은 여전히 일어난다는 뜻이에요. 마찬가지로 변수 치환을 완성하는 데 필요한 명령 치환은 -nocommands를 지정해도 일어나요.
치환 중 오류가 나면 subst는 그 오류를 반환해요. 명령이나 변수 치환 중 break 예외가 발생하면, 전체 치환의 결과는 예외를 일으킨 치환이 시작되는 지점까지의 치환된 문자열이 돼요. 명령이나 변수 치환을 평가하는 동안 continue 예외가 발생하면, 그 명령/변수 치환 전체가 빈 문자열로 치환돼요(그것이 잘 만들어진 Tcl인 한). return 예외가 발생하거나 명령/변수 치환 중 다른 반환 코드가 반환되면, 그 반환 값이 그 치환 자리에 대신 들어가요. 이렇게 해서 모든 예외적인 반환 코드가 subst에 '잡혀요'. subst 명령 자체는 오류를 반환하거나 성공적으로 완료하거나 둘 중 하나예요.
예제
subst는 치환을 할 때 큰따옴표나 중괄호(명령 치환 내부는 제외)를 특별히 다루지 않아요. 그래서
set a 44
subst {xyz {$a}}
는 "xyz {44}"를 반환하지 "xyz {$a}"를 반환하지 않아요. 그리고
set a "p\} q \{r"
subst {xyz {$a}}
는 "xyz {p} q {r}"를 반환하지 "xyz {p\} q \{r}"를 반환하지 않아요.
명령 치환을 수행할 때는 그 스크립트를 평가하는 데 필요한 변수 치환을 포함해요.
set a 44
subst -novariables {$a [format $a]}
는 "$a 44"를 반환하지 "$a $a"를 반환하지 않아요. 마찬가지로 변수 치환을 수행할 때는 변수 값을 가져오는 데 필요한 명령 치환을 포함해요.
proc b {} {return c}
array set a {c c [b] tricky}
subst -nocommands {[b] $a([b])}
는 "[b] c"를 반환하지 "[b] tricky"를 반환하지 않아요.
continue와 break 예외는 명령 치환이 나머지 명령 치환 부분과 나머지 문자열 각각의 치환을 막을 수 있게 해 줘요. 이로써 subst로 텍스트를 처리할 때 스크립트 작성자에게 더 많은 선택지가 생겨요. 예를 들어
subst {abc,[break],def}
는 "abc,"를 반환하지 "abc,,def"를 반환하지 않아요. 그리고
subst {abc,[continue;expr {1+2}],def}
는 "abc,,def"를 반환하지 "abc,3,def"를 반환하지 않아요.
다른 예외적인 반환 코드는 반환된 값을 그대로 치환해요.
subst {abc,[return foo;expr {1+2}],def}
는 "abc,foo,def"를 반환하지 "abc,3,def"를 반환하지 않아요. 그리고
subst {abc,[return -code 10 foo;expr {1+2}],def}
도 "abc,foo,def"를 반환하지 "abc,3,def"를 반환하지 않아요.