Jaki jest obecny separator dziesiętny?

29

Powiedzmy, że mam taki skrypt powłoki POSIX

  1. musi działać na różnych systemach / środowiskach, których nie kontroluję, oraz
  2. musi usunąć separator dziesiętny z ciągu emitowanego przez program, który przestrzega ustawień regionalnych.

Jak mogę wykryć separator dziesiętny w najbardziej ogólny sposób?

gboffi
źródło
Jaki rodzaj skryptu? Gdzie to działa? Zaktualizuj swoje pytanie, aby można było na nie odpowiedzieć.
X Tian
@XTian Ogólny skrypt powłoki, działający w systemie Unix / Linux. Del Celowo postawiłem pytanie w najbardziej ogólny sposób, ponieważ interesuje mnie najbardziej ogólna odpowiedź, jak wskazałem w ostatnim wierszu mojego pytania.
gboffi
1
@ StéphaneChazelas Skrypt POSIX! Szczerze mówiąc, zapomniałem, że używałem tcshw ... och, na pewno można powiedzieć, że jestem stary !!!
gboffi
1
Czy nie możesz uruchomić programu emitującego łańcuch w LC_ALL=Cśrodowisku?
Ángel
@ Ángel O tak, oczywiście, że mógłbym ...
gboffi

Odpowiedzi:

43

Zapytaj locale:

locale decimal_point

Spowoduje to wyświetlenie przecinka dziesiętnego przy użyciu bieżących ustawień regionalnych.

Jeśli potrzebujesz separatora tysięcy:

locale thousands_sep
Stephen Kitt
źródło
2
Przynajmniej z localeGNU libc, locale -k LC_NUMERICaby wyświetlić wszystkie ustawienia regionalne w kategorii LC_NUMERIC.
Stéphane Chazelas
3
@Kusalananda jest częścią POSIX .
Stephen Kitt
3
@muru printf "%'f"zrobiłby to dla printfimplementacji, które obsługują %f.
Stephen Kitt
2
@muru Jedynym znanym mi wbudowanym narzędziem, które może wypisać separator dziesiętny, jest to, że printfniektóre powłoki (np. dash) nie obsługują wyjścia zinternacjonalizowanego . W innej odpowiedzi Stéphane Chazelas wyjaśnił w komentarzu , że POSIX nie wymaga tego
gboffi
1
@StephenKitt Tak to jest. Dziwne, że jeszcze tego nie spotkałem. To nie pomaga, że ​​jestem w systemie, w którym takie użycie localenie jest obsługiwane.
Kusalananda
6

Jeśli jest to zshskrypt powłoki, możesz użyć $langinfospecjalnej tablicy asocjacyjnej w zsh/langinfomodule:

zmodload zsh/langinfo
radix=$langinfo[RADIXCHAR]

(to odwzorowuje do standardu nl_langinfo(RADIXCHAR), zobacz szczegóły man nl_langinfow twoim systemie; $langinfo[THOUSEP]separator tysięcy).

W bashskrypcie (również działałby zsh) powinieneś być w stanie go uzyskać bez tworzenia osobnego procesu za pomocą printfwbudowanego:

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

Aby przekonwertować liczbę z formatu ustawień regionalnych użytkownika na format ustawień regionalnych C, za pomocą powłoki ksh93 możesz to zrobić w następujący sposób:

$ 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
źródło
Czy może być najbardziej ogólny? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0}
gboffi
1
@ gboffi, działałoby to w niektórych internacjonalizowanych printfimplementacjach, które obsługują %f, ale nie wszystkie. %fobsługa nie jest wymagana przez POSIX. printfNa dashprzykład zawsze używa.
Stéphane Chazelas
re dashnie zinternacjonalizowany ... Właśnie okazało się, że ... tak najbardziej ogólne rozwiązanie jest uciekania się locale decimal_point, prawda?
gboffi
@ gboffi, prawdopodobnie. GNU awkmoże również interpretować liczby w bieżącym języku z trybem POSIX (choć nie obsługuje separatora tysięcy).
Stéphane Chazelas