zshの `print -P`のエスケープ変数

zshの `print -P`のエスケープ変数

print -P型指定子と引用符、バックスラッシュ、改行文字などの特殊文字を含む変数をエスケープして、渡されたときに文字通り印刷されるようにする方法を探しています。

だから本質的に、私はこれら2つを同じように印刷したいと思います。

> cat file.txt
> my_var="$(cat file.txt)"
> print -P "${<magic>my_var}"

私が使用するテストケースの良いサンプルファイルは次のとおりです。

Backslash \
Double Backslash \\

Single Quote '
Double Quote "

-----------------------
Escaped Linebreak \n
-----------------------

Color codes: %F{red}not red%f

Variable expansion $SHELL

私が得た最も近い問題は、${${(q+)my_var}//\%/%%}引用符、改行、バックスラッシュ、変数の拡張に関する問題でした。

$'Backslash Double Backslash \

Single Quote '
Double Quote "

-----------------------
Escaped Linebreak \n
-----------------------

Color codes: %F{red}not red%f

Variable expansion /usr/bin/zsh'

わかりましたprintf '%s\n' "$my_var"。しかし、実際には変数の周りに実際の書式がたくさんあるので、print -Pこれは私には適していません。残念ながら、print -P変数の周りと実際の変数で使用することはprintf機能しません。なぜなら、文字列演算が変数の内容に適用されることもあるからです。

答え1

${(q)…}そのバリアントは'…'"…"または$'…'引用符を使用しますが、引用符拡張はprint -P実行せず、バックスラッシュ拡張とヒント拡張のみを実行します(パーセントエスケープ拡張と有効になっているprompt_subst場合は置換を含む)。だから${(q)…}ここでは役に立たないと思います。

無効にすると、prompt_substバックスラッシュとパーセント記号を保護する必要があります。有効になったら、prompt_substドルとバックティックも保護する必要があります。

if [[ -o prompt_subst ]]; then
  print -P -- "${${${${my_var//\\/\\\\\\\\}//\%/%%}//\$/\\\\\$}//\`/\\\\\`}"
else
  print -P -- "${${my_var//\\/\\\\}//\%/%%}"
fi

答え2

目的はいくつかの文字列を印刷することです\x

print -P -- $string_to_undergo_both \
            ${string_to_undergo_prompt//\\/\\\\} \
            ${string_to_undergo_backslash//complex-brittle-expression} \
            ${string_to_undergo_none//complex-brittle-expression} \

次のように分割できます。

print  -P -n -- $string_to_undergo_both' '
print -rP -n -- $string_to_undergo_prompt' '
print     -n -- $string_to_undergo_backslash' '
print -r     -- $string_to_undergo_none

(このオプションが有効なprint -rP場合、withは自分だけでなくエスケープにも使用されるという点で依然として特別なので、代わりに出力されます。)promptsubst\$`print -rP '\\'\\\

またはprint -r --それを呼び出してawを印刷します(rKornシェルとの互換性のためにデフォルトでオンに\xなっている拡張機能を無効にするprint)、必要に応じてパラメータ拡張フラグを使用してプロンプト拡張またはバックスラッシュ拡張を有効にします。

print -r -- ${(g[o]%)string_to_undergo_both} \
            ${(%)string_to_undergo_prompt} \
            ${(g[o])string_to_undergo_backslash} \
            $string_to_undergo_none

${(flags):-literal-text}${(%):-%F{red}}引用符(プロンプト拡張など)を使用することも、$'...'バックスラッシュ拡張のためにリテラルテキスト(変数ではない)に対してこれを有効にすることもできます。

%%完全なプロンプト拡張(有効になっている場合は危険なアプリケーションを含むpromptsubst)とeパラメータ拡張、コマンド置換、および算術拡張を実行するには、パラメータ拡張フラグも参照してください。

の場合、printfバックスラッシュ拡張は、型パラメータと型ディレクティブの引数の両方で行われます(ただし、通常のCスタイルではなく後者の%bスタイルでは)。echoただし、迅速な拡張のための型ディレクティブはありません。

ただし、ヒント拡張を使用すると、配列を介して逐語テキストを渡すことができます(ただし、制御文字などの印刷できない文字は、一部の視覚表現(\n改行、^[ESC、U + FFFEなど)に変換されることに注意してください。 。\ufffe$psvar

$ psvar=( '\\' %% )
$ print -P 'first is %F{red}%1v%f, second is %F{green}%2v%f'
first is \\, second is %%

したがって、次のコマンドを使用してプロンプト拡張を有効にできますprintf

pprintf() {
  local psvar=("${(@)argv[2,-1]}")
  print -P -- "$1"
}
$ pprintf 'cwd: %~, host: %m, arbitrary printable string: "%1v"' '\\%%'
cwd: ~, host: myhost, arbitrary printable string: "\\%%"

(バックスラッシュ拡張もここで行われます。-r無効にするには追加してください)。

関連情報