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
되고 으로 확장됩니다 . 이 옵션이 설정되고 문자열이 프롬프트 문자열의 일부로 사용되는 경우 인수 확장, 명령 대체 및 산술 확장에 대해 평가됩니다. 그러므로 만약 , then 이 되고 가 됩니다 ."${(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
채워지기 전에 $c
변수 값으로 처리되도록 하는 데 사용해야 합니다 c
(이 점을 지적한 @StéphaneChazelas에게 감사드립니다).
$ 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
이는 다른 매개변수에 대한 참조로 표시되는 매개변수 $intermediate
인 ksh 에서 호출되는 것과 약간 비슷합니다 . 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