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반면 . 옵션이 설정되고 이 문자열이 프롬프트 문자열의 일부로 사용되면 매개변수 확장, 명령 대체 및 산술 확장에 대해 평가됩니다. 그렇다면 , 그러면 가 되고 가 됩니다 ."${(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하려면 플래그를 사용해야 합니다 (이 점을 지적한 @StéphaneChazelas에게 감사드립니다).$cc

$ 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

이는 ksh에서 다른 매개변수에 대한 참조로 표시되는 매개변수 $intermediate인 a 와 비슷합니다 . namerefZsh도 결국 이러한 기능을 갖게 될 수 있습니다. 깃발보다 훨씬 더 편리한 곳이 있습니다 (P).

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

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

값을 $foo다시 검사하게 되었고, 그 시점에서 명령 대체가 발견되어 실행되었습니다.

나머지 플래그는 몇 가지 간단한 특수 형식 지정 요령입니다. ( o)를 사용하여 일반 어휘(문자) 순서로 배열 요소를 정렬하고, ( )를 사용하여 역순으로 정렬하고 , 각각 ( ) 또는 ( )를 O사용하여 동일한 대소문자 독립적으로 수행하고 , 프롬프트를 확장합니다 . ( )로 이스케이프 (기억하기 쉬움), print가 p로 하는 것처럼 백슬래시 이스케이프를 확장하고, ( )로 모든 문자를 대문자로 강제하거나 ( ) 로 소문자로 강제하고, ( )로 문자열의 첫 번째 문자나 각 배열 요소를 대문자로 표시하고 , 표시합니다. ( )를 사용하여 이스케이프 시퀀스로 특수 문자를 사용합니다 . 그 정도면 계속 진행하기에 충분할 것입니다.oiOi%%ULCV

관련 정보