n
저는 사용자 정의 ZSH 프롬프트를 작업 중이며 문자열(예: 패딩을 위한 공백)에서 문자 시간을 반복하고 싶습니다 . 이 문자열은 다음과 같이 인쇄됩니다 print -rP
( -r
플래그는 에코 이스케이프 규칙을 무시하고 -P
플래그는 프롬프트 확장을 수행합니다).
일종의 문자열 대체를 사용하는 작업 코드가 있지만 어떻게 작동하는지 모르겠습니다. 어떤 이유로 인쇄하려는 문자 수에 2를 곱해야 하는데 이는 해킹처럼 느껴집니다.
$ n=3
$ c='a'
$ print -rP "${(l:$n::$c:)}" # why doesn't this work?
ca
$ print -rP "${(l:(( $n * 2 ))::$c:)}" # but this does?
aaa
그렇다면 1) 2를 곱할 때 이것이 작동하는 이유와 2) 문자열 내에서 문자를 반복하는 올바른 구문은 무엇입니까?
답변1
1) 왜 이것이 2를 곱했을 때 작동하는가?
확장 은 "${(l:3::$c:)}"
로 확장되는 c$c
반면 . 옵션이 설정되고 이 문자열이 프롬프트 문자열의 일부로 사용되면 매개변수 확장, 명령 대체 및 산술 확장에 대해 평가됩니다. 그렇다면 , 그러면 가 되고 가 됩니다 ."${(l:3*2::$c:)}"
$c$c$c
PROMPT_SUBST
c=a
c$c
ca
$c$c$c
aaa
세트 로 테스트 XTRACE
:
$ n=3 c=a zsh -o PROMPT_SUBST -xc 'print -rP -- "${(l:n::$c:)}"'
+zsh:1> print -rP -- 'c$c'
ca
$ n=3 c=a zsh -o PROMPT_SUBST -xc 'print -rP -- "${(l:n*2::$c:)}"'
+zsh:1> print -rP -- '$c$c$c'
aaa
2) 문자열 내에서 문자를 반복하는 올바른 구문은 무엇입니까?
매개 l
변수 확장 플래그는 이미 사용하고 있는 것과 동일한 방식으로 사용할 수 있습니다. 그러나 패딩 전에 문자열 인수를 변수 값으로 사용 p
하려면 플래그를 사용해야 합니다 (이 점을 지적한 @StéphaneChazelas에게 감사드립니다).$c
c
$ n=3 c=a zsh -xc 'print -r -- "${(pl:n::$c:)}"'
+zsh:1> print -r -- aaa
aaa
man zshexpn
이는 매개변수 확장 플래그에 대한 섹션 에 따라 이 구성에서 허용되는 유일한 매개변수 확장 형식입니다 .
p
$var
또는 이 옵션을 사용하면 문자열 인수가 변수 값으로 대체되는 형식일 수 있습니다 . 이 양식은 엄격합니다. 문자열 인수는 일반 매개변수 확장을 거치지 않습니다.
답변2
원래 표기법을 사용하면 원하는 것을 얻을 수 있습니다 p
.시작매개변수 플래그 중
print "${(pl:$n::$c:)}"
더 많은 정보와 기타 유용한 예를 보려면 섹션을 참조하세요.5.4.6: 더 많은 매개변수 플래그~에5장: 대체zsh 가이드 중. 대문자는 언급되어 있지만 다음 은 언급 P
되지 않습니다 p
.
다음은 몇 가지 다른 매개변수 플래그입니다. 나는 이것들 중 일부를 반복하고 있습니다. 매우 유용한 방법은 t
매개변수의 유형을 알려주는 것입니다. 3장에도 이런 내용이 나왔습니다. 가장 일반적인 용도는 매개변수를 사용하기 전에 매개변수의 기본 유형을 테스트하는 것입니다.
if [[ ${(t)myparam} != *assoc* ]]; then
# $myparam is not an associative array. Do something about it.
fi
또 다른 매우 유용한 유형은 문자열의 왼쪽 또는 오른쪽 패딩을 지정된 길이로 지정하고 선택적으로 공백 대신 사용할 지정된 채우기 문자열을 사용하는 것입니다. 문제의 문자열 바로 옆에 일회용 문자열을 지정할 수도 있습니다.
foo='abcdefghij'
for (( i = 1; i <= 10; i++ )); do
goo=${foo[1,$i]}
print ${(l:10::X::Y:)goo} ${(r:10::X::Y:)goo}
done
꽤 예쁜 것을 인쇄합니다:
XXXXXXXXYa aYXXXXXXXX
XXXXXXXYab abYXXXXXXX
XXXXXXYabc abcYXXXXXX
XXXXXYabcd abcdYXXXXX
XXXXYabcde abcdeYXXXX
XXXYabcdef abcdefYXXX
XXYabcdefg abcdefgYXX
XYabcdefgh abcdefghYX
Yabcdefghi abcdefghiY
abcdefghij abcdefghij
s
콜론(( ) 및 ( ) 플래그 에 대해 설명했듯이 다른 문자일 수 있음 j
)은 항상 인수 앞과 뒤에 쌍으로 나타나므로 세 개의 인수를 사용하면 그 사이의 콜론이 두 배가 됩니다. :Y:
부분과 부분을 놓치고 :X:
무슨 일이 일어나는지 볼 수 있습니다. 채우기 문자열은 단일 문자일 필요는 없습니다. 필러 공간에 정확한 횟수가 맞지 않으면 삽입되는 매개변수 인수에서 가장 먼 끝에서 마지막 반복이 잘립니다.
두 개의 매개변수는 매개변수 대체 값으로 특별한 작업을 수행하기를 원한다는 것을 쉘에 알려줍니다. ( P
) 플래그는 값이 매개변수 이름으로 처리되도록 강제하여 이중 대체 효과를 얻습니다.
% final=string
% intermediate=final
% print ${(P)intermediate}
string
이는 ksh에서 다른 매개변수에 대한 참조로 표시되는 매개변수 $intermediate
인 a 와 비슷합니다 . nameref
Zsh도 결국 이러한 기능을 갖게 될 수 있습니다. 깃발보다 훨씬 더 편리한 곳이 있습니다 (P)
.
더 강력한 플래그는 ( e
)로, 모든 형태의 단일 단어 대체에 대해 값을 다시 검색하도록 합니다. 예를 들어,
% foo='$(print $ZSH_VERSION)'
% print ${(e)foo}
4.0.2
값을 $foo
다시 검사하게 되었고, 그 시점에서 명령 대체가 발견되어 실행되었습니다.
나머지 플래그는 몇 가지 간단한 특수 형식 지정 요령입니다. ( o
)를 사용하여 일반 어휘(문자) 순서로 배열 요소를 정렬하고, ( )를 사용하여 역순으로 정렬하고 , 각각 ( ) 또는 ( )를 O
사용하여 동일한 대소문자 독립적으로 수행하고 , 프롬프트를 확장합니다 . ( )로 이스케이프 (기억하기 쉬움), print가 p로 하는 것처럼 백슬래시 이스케이프를 확장하고, ( )로 모든 문자를 대문자로 강제하거나 ( ) 로 소문자로 강제하고, ( )로 문자열의 첫 번째 문자나 각 배열 요소를 대문자로 표시하고 , 표시합니다. ( )를 사용하여 이스케이프 시퀀스로 특수 문자를 사용합니다 . 그 정도면 계속 진행하기에 충분할 것입니다.oi
Oi
%
%
U
L
C
V