Welches ist das aktuelle Dezimaltrennzeichen?

29

Angenommen, ich habe ein POSIX-Shell-Skript, das

  1. muss auf verschiedenen Systemen / Umgebungen ausgeführt werden, die ich nicht kontrolliere, und
  2. muss das Dezimaltrennzeichen aus einer Zeichenfolge entfernen, die von einem Programm ausgegeben wird, das die Gebietsschemaeinstellungen berücksichtigt.

Wie kann ich das Dezimaltrennzeichen am allgemeinsten erkennen?

gboffi
quelle
Was für ein Drehbuch? Wo läuft es? Bitte aktualisieren Sie Ihre Frage, damit sie beantwortet werden kann.
X Tian
@XTian Ein generisches Shell-Skript, das auf einem Unix / Linux-System ausgeführt wird. ֎ Ich habe die Frage absichtlich ganz allgemein gestellt, weil ich an der allgemeinsten Antwort interessiert bin, die ich in der letzten Zeile meiner Frage angegeben habe.
gboffi
1
@ StéphaneChazelas Ein POSIX-Skript! Ehrlich tcshgesagt, ich habe vergessen, dass ich in ... verwendet habe, oh mein Gott, du kannst definitiv sagen, dass ich ALT bin !!!
gboffi
1
Können Sie das von Zeichenfolgen ausgegebene Programm nicht in einer LC_ALL=CUmgebung ausführen ?
Ángel
@ Ángel Oh ja, natürlich könnte ich ...
gboffi

Antworten:

43

Fragen Sie locale:

locale decimal_point

Dadurch wird der Dezimalpunkt mit den aktuellen Gebietsschemaeinstellungen ausgegeben.

Wenn Sie das Tausendertrennzeichen benötigen:

locale thousands_sep
Stephen Kitt
quelle
2
Und zumindest mit der localevon der GNU libc, locale -k LC_NUMERICum alle Gebietsschemaeinstellungen in der Kategorie LC_NUMERIC aufzulisten.
Stéphane Chazelas
3
@ Kusalananda ist Teil von POSIX .
Stephen Kitt
3
@muru printf "%'f"würde es tun, für printfImplementierungen, die unterstützen %f.
Stephen Kitt
2
@muru Das einzige mir bekannte eingebaute Element , das ein Dezimaltrennzeichen ausgeben kann, ist, printfund einige Shell (z. B. dash) unterstützen keine internationalisierte Ausgabe. In einer anderen Antwort erklärte Stéphane Chazelas in einem Kommentar , dass es von POSIX
gboffi
1
@StephenKitt So ist es. Es ist nur seltsam, dass ich noch nie darauf gestoßen bin. Es hilft nicht, dass ich auf einem System bin, auf dem diese Verwendung localenicht unterstützt wird.
Kusalananda
6

Wenn es sich um ein zshShell-Skript handelt, können Sie das $langinfospezielle assoziative Array in derzsh/langinfo Modul verwenden:

zmodload zsh/langinfo
radix=$langinfo[RADIXCHAR]

(das entspricht dem Standard nl_langinfo(RADIXCHAR), sieheman nl_langinfo Details finden auf Ihrem System; $langinfo[THOUSEP]das Tausendertrennzeichen).

In einem bashSkript (würde auch funktionieren zsh) sollten Sie in der Lage sein, es printfabzurufen, ohne einen separaten Prozess mit dem eingebauten Befehl zu forken:

printf -v radix %.1f 1 && radix=${radix:1:1}

Um eine Zahl aus dem Gebietsschema-Format des Benutzers in das C-Gebietsschema-Format zu konvertieren, können Sie mit der ksh93-Shell wie folgt vorgehen:

$ locale title
German locale for Germany
$ x=1.123.456,78 ksh -c 'typeset -F x="$x"; LC_ALL=C; printf "%.23g\n" "$x"'
1123456.78
Stéphane Chazelas
quelle
Am allgemeinsten, könnte es sein? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0}
gboffi
1
@gboffi, das würde in einigen internationalisierten printfImplementierungen funktionieren, die dies unterstützen %f, aber nicht in allen. %fSupport wird von POSIX nicht verlangt. Die printfvon dashzum Beispiel verwendet immer.
Stéphane Chazelas
re dashnicht internationalisiert ... Ich habe gerade festgestellt , dass ... so die allgemeinste Lösung zurückgreift locale decimal_point, nicht wahr?
gboffi
@ Gboffi, wahrscheinlich. GNU awkkann Zahlen im aktuellen Gebietsschema auch im POSIX-Modus interpretieren (behandelt jedoch nicht das Tausendertrennzeichen).
Stéphane Chazelas