printf를 사용하여 인수로 전달된 유니코드 문자를 디코딩하려고 합니다.

printf를 사용하여 인수로 전달된 유니코드 문자를 디코딩하려고 합니다.

다음과 같이 파이프로 연결되는 일부 유니코드 코드를 인쇄하려고 합니다.

echo 0024 0025 | xargs -n1 echo # one code per line
  | xargs printf '\u%s\n'

이것을 얻기를 바라고 있다

$
%

하지만 이것이 내가 얻은 것입니다

printf: missing hexadecimal number in escape

몇 번의 시행착오 끝에 실제로는 두 가지 작은 문제가 생겼는데, 한 가지 문제는 이해가 되고 다른 하나는 완전히 미스터리처럼 보입니다.


문제 1:

printf '\u%s\n' 0024 0025

나에게 이것을 준다

-bash: printf: missing unicode digit for \u
\u0024
-bash: printf: missing unicode digit for \u
\u0025

문제 2:

> # use built-in for $
> printf '\u0024\n'
$
> # use exe for $
> which printf
/usr/bin/printf
> /usr/bin/printf '\u0024\n'
$
> # now use built-in for %
> printf '\u0025\n'
%
> # but look what happens when we use exe for % !!!!
> /usr/bin/printf '\u0025\n'
/usr/bin/printf: invalid universal character name \u0025

( >for 를 사용하면 출력에서 $​​를 볼 수 있습니다 )$

어떤 이유로 일부 문자는 exe 버전에서 작동하지만 일부 문자는 내장 printf에서 작동하더라도 작동하지 않습니다.


그래서 여기에 문제 #2가 아닌 경우에 작동할 수 있는 해결 방법이 있습니다(하지만 원래 아이디어보다 상당히 느릴 수 있습니다).

echo 0024 0025 | xargs -n1 echo # one item per line
  | xargs -I {} printf '\u{}\n'

하지만 문제 #2로 인해 절반 정도는 작동합니다.

$ echo 0024 0025 | xargs -n1 echo | xargs -I {} printf '\u{}\n'
$
printf: invalid universal character name \u0025

($는 나오지만 %는 에러가 납니다)


그래서 내 질문은 다음과 같습니다.

-인수당 한 번이 아닌 한 번만 printf를 실행할 수 있도록 printf를 숫자 코드와 함께 작동시키는 방법이 있습니까 -I?

printf- 내장 기능은 신경 쓰지 않지만 printfexe는 마음에 들지 않지만 에 대해서만 마음에 들지 %않고 에 대해서는 마음에 들지 않는데 내가 뭘 잘못하고 있는 걸까요 $?

답변1

이중 확장 문제( \u이전에 처리됨 )를 방지하려면 최소한 Bash에서는 다음을 %s사용할 수 있습니다 .%bprintf

printf '%b\n' \\u0024 \\u0025

다양한 방법으로 입력을 사전 처리할 수 있습니다.

set 0024 0025
printf '%b\n' "${@/#/\\u}"

독립형 printf,GNU coreutils에 구현된 대로에는 유니코드 문자 사양에 대해 다음과 같은 제한 사항이 있습니다.

printfISO C 99에 도입된 두 가지 문자 구문인 ' \u'(16비트 유니코드(ISO/IEC 10646) 문자의 경우 4자리 16진수로 지정됨)을 해석합니다.으아아아\U, 32비트 유니코드 문자의 경우 ' '(8자리 16진수로 지정)으아아아아아. 로케일 printf에 따라 유니코드 문자를 출력합니다 LC_CTYPE. U+0000…U+009F, U+D800…U+DFFF 범위의 유니코드 문자는 U+0024($), U+0040(@) 및 U+0060(`)을 제외하고 이 구문으로 지정할 수 없습니다. .

%이것이 왜 이런 방식으로 생산할 수 없는지 설명합니다 .

답변2

표준 printf유틸리티는 이스케이프 시퀀스를 지원하지 않습니다 \uxxxx. 다음을 참조하세요.https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html

이것이 작동할 수 있다고 가정하면 몇 가지 구현(예: 내장 ksh)에 존재할 수 있지만 일반적으로 지원될 수는 없는 확장에 따라 달라집니다. 표준문서를 참고하세요 printf.

또 다른 문제는 전화를 걸었다고 가정하는 것 같습니다.

printf '\u%s\n' 123

결과는 다음과 같습니다.

printf '\u123\n'

printf형식 문자열 요소를 요소별로 구문 분석하고 예상되는 형식 문자열이 표시되지 않으므로 이는 작동하지 않습니다 .

bash따라서 를 사용하여 스크립트를 실행하는 경우에도 \uxx두 개의 16진수 숫자가 뒤에 나오고 이스케이프 시퀀스가 ​​문자 그대로 형식 문자열에 나타나면 백슬래시 이스케이프가 확장될 것으로 예상할 수 있습니다. 4개의 16진수를 확장하려면 \Uxxxx형식 문자열에 문자 그대로 포함해야 합니다.

관련 정보