jo...@schily.net:
>>>bosh
>>>$ printf '\x77a\n'
>>>\x77a
>>
>>Definiert POSIX die Bedeutung von «\x» in der
>>Formatierungszeichenkette von «printf»?Â
>
>Nein, und daher darf eine konforme Implementierung das auch nicht
>expandieren. Eine zulässige Erweiterung muß so funktionieren, daß
>kein vom Standard abweichendes Verhalten entsteht.
>
>>Ich würde mich auf die in
>><
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html#tag_20_94_13>
>>genannten Escape�Sequenzen '\\', '\a', '\b', '\f', '\n', '\r', '\t',
>>'\v' und "\ddd", wobei ddd eine ein� bis dreistellige Oktalzahl ist,
>>beschränken.Â
>
>Das ist so keine brauchbare Aussage, weil Konformität ja nicht nur
>bedeutet daß dokumentierte Escape Sequenzen expandiert werden,
>sondern auch das keine weiteren Dinge expandiert werden, bei denen
>man nicht damit rechnet.
>
Damit ist also festgelegt, dass «\xzz», wobei «zz» zwei
Sedezimalziffern sind, nicht als Escape‐Sequenz mit Byte‐Wert im
Sedezimalsystem expandiert werden darf, sondern wörtlich verstanden
werden muss. Richtig?
>>>$ printf '%b\n' '\000a'
>>>a
>>
>>Da fehlt entweder in der Ausgabe ein Byte oder es ist nur nicht zu
>>sehen. POSIX erwartet als Ausgabe eine Folge von 3 Bytes,
>>deutlicher zu sehen, wenn man die Ausgabe durch «od» schiebt.Â
>>Das Kommando
>
>Ich habe das angeführt, weil diverse Shells (incl. dash) das Null
>Byte entweder nicht exandieren, oder das 'a' danach nicht mehr
>ausgeben, weil sie den String z.B. erst expandieren und dann an ein
>normales printf(3) weiterreichen.
Ah, danke. Das kommt dann auch ohne «od» an den Tag.
>>«ksh» ist bei mir nicht installiert. Mit «bash» und
>>«dash», sowie standalone «printf» sieht es auf einem Debian
>>Buster Linux – nicht gerade für die neusten Fassungen der
>>Utilities bekannt –, jeweils durch das Kommando
>
>Interessant ist schon, daß bash und ksh \x expandieren, das aber in
>unterschiedlicher Weise.
>
>Auch interessant ist, daß die meisten installierten dash Versionen
>im Feld das Null Byte nicht korrekt expandieren. Ich hatte dieses
>Problem mal veröffentlicht, als ich vor 5 Jahren ein konformes
>printf(1) als Builtin Kommando für den Bourne Shell entwickelt
>habe. Der Bug scheint vor einem knappen Jahr in dash reariert
>worden sein, damit ist diese Version aber noch nicht bei Allen
>Nutzern vor Ort.
>
Vor einem knappen Jahr? Mein Debian‐Buster‐«dash» hat als Datum der
letzten Änderung des Dateiinhalts 2019-01-17T19:08:32-00:00. Und da
Debian eher dafür bekannt ist, gut abgehangene Software
mitzubringen, glaube ich kaum, dass es noch aktuelle Betriebssysteme
mit in dieser Hinsicht defektem «dash»‐«printf» gibt.
>Um die Probleme mit der nicht-konformen Expansion von \x in ksh und
>bash zu vermeiden, gleichzeitig aber mehr Expansionsmöglichkeiten
>zu bekommen, werden wir im nächsten POSIX Standard (ISSUE-8) der
>vermutlich in einem Jahr kommt, die Expansion $'...' einführen.
>Damit wird \uxxxx, \uxxxxxxxx, \xnnnn, \xnnnnnnnn unterstützt.
Verstehe ich Dich darin richtig, dass diese Expansionen dann eine
Sache der Shell‐Kommandozeile und nicht von «echo» oder «printf»
sind?
>Wann das dann in den Shells ankommt, wird sich zeigen. Ich habe für
>den Bourne Shell (bosh) entschieden, noch ein paar Monate zu
>warten, weil aktuell noch nicht sichergestellt ist, daß sich daran
>nichts mehr im Einzelnen ändert.
>
Sehe ich auch so. Überstürzter Aktionismus verrennt sich leicht.
>Aktuell gibt es bei dash übrigens folgende mir bekannte
>Abweichungen vom POSIX Standard, wobei ich mal die Annahme mache,
>daß Linux sich als UNIX-kompatibel bezeichnet und daher alle XSI
>Erweiterungen aus POSIX für eine POSIX Konformität implementiert
>werden müssen:
>
>- Kein Support für multi-byte Zeichen
>
Bereits deshalb scheidet für mich «dash» als Standard‐Shell aus; und
über «Aber dann bootet meine Workstation schneller, als wenn ich
‹bash› (oder einen anderen auf Linux mitgelieferten Shell) nehme!»
kann ich nur den Kopf schütteln.
>- "echo '\1'" wird nach ^A expandiert, was verboten ist.
> Gefordert ist im Standard "echo '\0001'"
>
>- "printf '%b\n' '\1'" wird expandiert, obwohl das wie bei echo
> verboten ist, denn \b soll ja echo Kompatibilität liefern.
Ja. Ein vorsichtiger Anwender übergibt im Fall, dass «\1»
ausgegeben werden soll, einem XSI‐«echo» oder printf die
Zeichenkette «\\1».
Dafür ist die Escape‐Sequenz «\\» mit der Expansion zu «\» ja
schließlich da.
Und wenn es darum geht, bei XSI‐«echo» oder bei «printf» mit «%b»
eine Escape‐Sequenz mit Oktalziffern zu verwenden, schreibt der
vorsichtige Anwender hinter «\0» immer genau 3 weitere Ziffern,
damit er bei
# Von der Variablen "var" sei hier nur bekannt, dass
# der Inhalt mittels '%b' expandiert werden soll:
#
printf '%b\n' '\01'"$var"
nicht böse auf die Schnauze fällt, wenn der Inhalt der Variablen
«var» zufällig mit mindestens einer Oktalziffer (die nicht dafür
gedacht ist, Teil einer Escape‐Sequenz zu werden) beginnt.
Dazu kommt, dass es bei
printf '\ddd'
leicht anders aussieht: Da wird eine 1‐ bis 3‐stellige Oktalzahl
verlangt, und sie braucht keine führenden Nullen zu enthalten. Ich
vermute, dass diesen Unterschied längst nicht alle «printf»‐Anwender
auf dem Schirm haben.
Ich gebe zu: Der Fall, dass die Formatierungszeichenkette aus
verschiedenen Quellen zusammengesetzt wird, wie etwa im Beispiel
# Von der Variablen "var" sei hier nur bekannt, dass der
# Inhalt Teil der Formatierungszeichenkette werden soll:
#
printf '\1'"$var"'\n' ...
zu sehen, und dass im Variableninhalt dabei freie Ziffern
herumstehen, ist sicherlich geringer.
Insgesamt halte ich mich als vorsichtiger Anwender an die Regel:
«\» ist vollständig für Escape‐Sequenzen reserviert. Alle
Zeichenfolgen, die wie Escape‐Sequenzen aussehen, sind entweder
bereits definiert oder als (noch) unbestimmt reserviert.
Wenn ich einen «\» ausgeben will, übergebe ich XSI‐«echo» oder
«printf» in der Formatierungszeichenkette oder einem «%b»
zugeordneten Parameter stets zwei, egal, ob danach weitere Zeichen
folgen, die einen einzelnen «\» zu einer Escape‐Sequenz
vervollständigen könnten oder nicht. Alles andere ist aus
Anwendersicht (s. o.) ein Spiel mit dem Feuer. Da hätte ich gerne,
dass das im nächsten Standard bei «printf» und XSI‐«echo» etwa im
Abschnitt «APPLICATION USAGE» als best practice empfohlen wird.
Des weiteren würde ich mir wünschen, dass in den Abschnitten
«APPLICATION USAGE» beispielsweise von «echo» und «printf»
Zeichenketten, die keine Variablen‐Expansionen oder command
substitution darstellen, in Apostrophe statt Anführungszeichen
gesetzt werden.
Dass beispielsweise
printf "%s\n" "Hello, world!"
dasselbe wie
printf '%s\n' 'Hello, world!'
bedeutet, ist nur dem «Zufall» zu verdanken, dass der Shell bei sowohl
«"\n"» wie auch bei «'\n'» den Parameter «\n» an «printf» übergibt.
Anders sieht es beispielsweise bei
printf '%4s%s\n' \
'/' '\' '//' '\\' '///' '\\\' \
'\\\' '///' '\\' '//' '\' '/'
im Vergleich zu
printf '%4s%s\n' \
"/" "\" "//" "\\" "///" "\\\" \
"\\\" "///" "\\" "//" "\" "/"
aus.