Versuch, printf zum Dekodieren von Unicode-Zeichen zu verwenden, die als Argumente übergeben werden

Versuch, printf zum Dekodieren von Unicode-Zeichen zu verwenden, die als Argumente übergeben werden

Ich versuche, einige Unicode-Codes auszudrucken, die ich so einleite

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

hoffe, dies zu bekommen

$
%

aber das ist, was ich bekomme

printf: missing hexadecimal number in escape

Nach einigem Herumprobieren habe ich tatsächlich zwei kleinere Probleme, eines ergibt irgendwie Sinn, das andere scheint ein komplettes Rätsel zu sein.


Problem 1:

printf '\u%s\n' 0024 0025

gibt mir das

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

Problem 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

(verwenden Sie >„for“ , damit Sie es in der Ausgabe $sehen können )$

Aus irgendeinem Grund funktionieren einige Zeichen mit der EXE-Version, andere jedoch nicht, obwohl alle mit dem integrierten Printf funktionieren.


hier ist also ein Workaround, der funktionieren würde, wenn es Problem Nr. 2 nicht gäbe (aber möglicherweise deutlich langsamer wäre als meine ursprüngliche Idee)

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

aber aufgrund von Problem Nr. 2 funktioniert es nur halb:

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

($ kommt heraus, aber % bringt einen Fehler)


Meine Fragen lauten also:

-Gibt es eine Möglichkeit, printf mit dem Zahlencode zum Laufen zu bringen, sodass ich printf einmal ausführen kann, anstatt einmal pro Argument mit -I?

-Was mache ich falsch, dass es dem printfintegrierten Programm nichts ausmacht, printfder exe aber nicht gefällt, aber nur für %und nicht für $?

Antwort1

Um das Problem der doppelten Erweiterung ( \uwird vor verarbeitet %s) zu vermeiden, können Sie %bzumindest in Bash Folgendes verwenden printf:

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

Sie können Ihre Eingaben auf verschiedene Arten vorverarbeiten:

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

Der printfeigenständigewie in GNU Coreutils implementiert, unterliegt den folgenden Einschränkungen hinsichtlich Unicode-Zeichenspezifikationen:

printfinterpretiert zwei in ISO C 99 eingeführte Zeichensyntaxen: ' \u' für 16-Bit Unicode (ISO/IEC 10646) Zeichen, angegeben als vier hexadezimale Ziffernhhhhund ' \U' für 32-Bit-Unicode-Zeichen, angegeben als acht hexadezimale Ziffernhhhhhhhh. printfgibt die Unicode-Zeichen entsprechend der LC_CTYPELändereinstellung aus. Unicode-Zeichen in den Bereichen U+0000…U+009F, U+D800…U+DFFF können mit dieser Syntax nicht angegeben werden, mit Ausnahme von U+0024 ($), U+0040 (@) und U+0060 (`).

%Dies erklärt, warum Sie auf diese Weise nicht produzieren können .

Antwort2

Das Standarddienstprogramm printfunterstützt keine \uxxxxEscape-Sequenzen, siehe:https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html

Die Annahme, dass dies funktionieren könnte, hängt von Erweiterungen ab, die in einigen Implementierungen (z. B. in einem kshintegrierten) vorhanden sein können, von denen jedoch nicht erwartet werden kann, dass sie allgemein unterstützt werden. Siehe das printfStandarddokument.

Ein weiteres Problem scheint Ihre Annahme zu sein, dass der Aufruf

printf '\u%s\n' 123

würde zum selben Ergebnis führen wie der Aufruf von:

printf '\u123\n'

Dies funktioniert nicht, da printfdie Formatzeichenfolge Element für Element analysiert wird und die erwartete Formatzeichenfolge nicht angezeigt wird.

Selbst wenn Sie also bashzur Ausführung des Skripts verwenden, können Sie erwarten, dass der \uxxBackslash-Escape erweitert wird, wenn zwei Hexadezimalziffern folgen und die Escape-Sequenz wörtlich in der Formatzeichenfolge vorkommt. Wenn Sie 4 Hexadezimalziffern erweitert haben möchten, müssen Sie wörtlich in der Formatzeichenfolge vorkommen \Uxxxx.

verwandte Informationen