私はこのようにパイプするいくつかのユニコードコードをprintfしようとしています
echo 0024 0025 | xargs -n1 echo # one code per line
| xargs printf '\u%s\n'
これを手に入れたい
$
%
しかし、これは私が得るものです
printf: missing hexadecimal number in escape
試行錯誤の末、実際には2つの小さな問題があります。1つは理にかなっており、もう1つは完全な謎のようです。
問題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
(>
に$
を使用すると、出力で$
を確認できます)
何らかの理由で、一部の文字は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
($は出ますが、%はエラーになります)
だから私は私の質問だと思います:
-I
を使用して、引数ごとに1回ではなく、printfを1回実行できるように、printfを数値コードで動作させる方法はありますか?
-printf
ビルトインが気にしないが、printf
exeは気に入らないが、%
のみであり、$
ではないことの何が問題なのでしょうか。 ?
二重展開の問題(\u
が%s
の前に処理される)を回避するには、少なくともBash printf
で%b
を使用できます。
printf '%b\n' \\u0024 \\u0025
入力はさまざまな方法で前処理できます。
set 0024 0025
printf '%b\n' "${@/#/\\u}"
スタンドアロンprintf
、 GNU coreutils で実装されている)は、Unicode文字仕様に次の制限があります。
printf
は、ISO C 99で導入された2つの文字構文を解釈します。4ビットの16進数として指定された16ビットUnicode(ISO/IEC 10646)文字の '\u
' hhhh、および32ビットUnicode文字の '\U
'、8桁の16進数として指定hhhhhhhh 。printf
は、LC_CTYPE
ロケールに従ってUnicode文字を出力します。 U + 0024($)、U + 0040(@)、およびU + 0060( `)を除き、U + 0000…U + 009F、U + D800…U + DFFFの範囲のUnicode文字はこの構文では指定できません。 。
これが、この方法で%
を作成できない理由を説明しています。
標準のprintf
ユーティリティは\uxxxx
エスケープシーケンスをサポートしていません。以下を参照してください https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
これが機能すると想定すると、いくつかの実装(たとえばksh
組み込み)に存在する可能性がある拡張機能に依存しますが、一般的にサポートされるとは期待できません。 printf
標準ドキュメントを参照してください。
別の問題は、
printf '\u%s\n' 123
次の呼び出しと同じ結果になります:
printf '\u123\n'
printf
はフォーマット文字列を要素ごとに解析し、予期されるフォーマット文字列を認識しないため、これは機能しません。
したがって、bash
を使用してスクリプトを実行している場合でも、2つの16進数が続き、エスケープシーケンスが文字列形式で表示される場合は、\uxx
バックスラッシュエスケープが展開されることを期待できます。 4桁の16進数を展開したい場合は、フォーマット文字列に文字どおり\Uxxxx
を含める必要があります。