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説明したように、他の文字にすることができます)は常にパラメータの前後にペアで表示されるため、3つのパラメータの場合は中間コロンが2倍になります。部分を:Y:1つずつ見逃して、何が起こるのかを見ることができます:X:。パディング文字列は単一文字である必要はありません。パディングスペースに正確な回数が合わない場合、最後の反復は挿入された引数引数から最も遠い端で切り捨てられます。

両方のパラメータは、パラメータで置き換えられた値に対して特別なアクションを実行したいシェルを示します。 (P)フラグは、値がパラメータ名として扱われるように強制し、二重置換効果を取得します。

  % final=string
  % intermediate=final
  % print ${(P)intermediate}
  string

これは、他のパラメータへの参照として表示されるパラメータ$intermediatekshから呼び出されるものと少し似ています。namerefZshは最終的にこれらの機能を持つことができ、いくつかの場所ではフラグよりも便利です(P)

より強力なフラグは(e)で、すべての形式の単一単語置換に対して値を再取得します。例えば、

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

値を再確認し、$fooコマンド置換を見つけて実行します。

残りのフラグは、いくつかの単純な特殊書式設定トリックです。o配列要素を通常の語彙(文字)順にソートするには()を使用し、逆順にソートするには()を使用し、大文字と小文字を区別せずに同じ操作を実行するにはそれぞれ()または()を使用しO、拡張します。ヒント - ()でエスケープする(覚えやすい)、printのようにバックスラッシュエスケープをpに展開し、すべての文字を()で大文字または()で小文字に、大文字の文字列または()で各配列要素を表示する最初番目の文字エスケープシーケンスである特殊文字の前には()が付きます。続行するにはこれで十分です。oiOi%%ULCV

関連情報