zsh의 `print -P`에 대한 이스케이프 변수

zsh의 `print -P`에 대한 이스케이프 변수

print -P형식 지정자와 따옴표, 백슬래시, 개행 문자 등의 특수 문자가 포함된 변수를 이스케이프 하여 전달될 때 문자 그대로 인쇄되도록 하는 방법을 찾고 있습니다 .

그래서 본질적으로 나는 이 두 개가 동일하게 인쇄되기를 원합니다.

> 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비활성화하려면 추가하세요).

관련 정보