zsh 프롬프트에서 char n 번 반복

zsh 프롬프트에서 char n 번 반복

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$cPROMPT_SUBSTc=ac$cca$c$c$caaa

컬렉션으로 테스트하세요 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(매개변수 확장 플래그 섹션에 있음) 에 따르면 이는 이 구성에서 허용하는 유일한 매개변수 확장 형식입니다 .

pprint이 매개변수 뒤에 설명된 모든 플래그에 대한 내장 문자열 매개변수와 동일한 이스케이프 시퀀스를 인식합니다.

또는 이 옵션을 사용하면 문자열 인수가 다음 형식을 취할 수 있으며, $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 에서 호출되는 것과 약간 비슷합니다 . namerefZsh는 결국 이러한 기능도 갖게 될 수 있으며 일부 장소에서는 플래그보다 더 편리합니다 (P).

더 강력한 플래그는 ( e)로, 모든 형태의 단일 단어 대체에 대해 값을 다시 검색하도록 합니다. 예를 들어,

  % foo='$(print $ZSH_VERSION)'
  % print ${(e)foo}
  4.0.2

값을 다시 확인 $foo하고 명령 대체를 찾아서 수행합니다.

나머지 플래그는 몇 가지 간단한 특수 형식화 트릭입니다. o배열 요소를 일반 어휘(문자) 순서로 정렬하려면 ( )를 사용하고, 역순으로 정렬하려면 ( )를 사용하고, 대소문자를 구분하지 않고 동일한 작업을 수행하려면 각각 ( ) 또는 ( )를 사용하고 O, 확장합니다. 팁 - ( )로 이스케이프 처리(기억하기 쉬움), print처럼 백슬래시 이스케이프를 p로 확장, 모든 문자를 ( )로 대문자 또는 ( )로 소문자로, 대문자 문자열 또는 ( )로 각 배열 요소를 표시하는 첫 번째 문자 이스케이프 시퀀스인 특수 문자 앞에는 ( )가 붙습니다. 계속하려면 이 정도면 충분합니다.oiOi%%ULCV

관련 정보