2024年6月15日(土) 17:24 Léa Gris <lea.g...@noiraude.net>: > Indeed printf only knows the string value. But Bash know the variable > has a numeric flag when doing the value expansion, so it expands it > using the current LC_NUMERIC locale in this specific case.
Ah, OK. I misunderstood your suggestion somehow differently (such that the expansion result would still use the period as a radix character, but the `print' builtin would automatically convert the format to the one with the locale-dependent radix character before it starts to interpret the arguments). > # Numeric format use comma as radix separator > LC_NUMERIC=fr_FR.UTF8 > > # Numeric variable uses the C locale format internally > declare -i floatVar=3.1415 > > # Printf does not have to know about the variable type > # as it is expanded in the current LC_NUMERIC format > printf '%.2f\n' "$floatVar" > # Prints 3,14 In this case, what is actually stored in the variable floatVar? `3.14' or `3,14' (probably the former if I do not misunderstand)? In other words, at which point does the conversion happens, in the assignment phase or the parameter expansion phase? If the conversion happens in the assignment phase, `floatVar' would not be able to use in arithmetic expressions, which seems unreasonable. If the conversion happens in the parameter expansion phase, it is different from the traditional behavior of parameter expansions. > # Same when it is expanded to assign another variable > # stringVar=3,1415 > # Since the string expansion of numeric variable uses the > # LC_NUMERIC format > stringVar=$floatVar > > # Same rule applies when expanding a numerical context to a string: > echo "$((2 * 3.14))" > # Prints the string 6,28 because LC_NUMERIC=fr_FR.UTF8 > > # Do not use string expansion to assign numeric value or it will fail > # with different locale. Use a numeric context to assign. > # Do: > (( arc = 2 * floatVar )) > # Don't: > # arc=$((2 * floatVar )) So this means that the arithmetic expansions $(()) would produce a format incompatible with the arithmetic expression. This seems inconsistent to me, but it might be a valid option if there is no other option. ---- I still feel it would be best if POSIX could be updated to allow the implementations to extend the interpretation when the conversion by strtod(3) fails. The current restriction is not an explicit one but something deduced from the four statements of the POSIX: 1) the floating-point conversion (%f, etc) of the printf utility is performed by strtod(3), 2) strtod(3) uses LC_NUMERIC to determine the radix character, 3) strtod(3) "fails" by setting endptr = nptr when the string does not have an expected form, 4) the printf utility needs to print a diagnostic message and fail when the argument is not converted to a value appropriate to the conversion specification (%f, etc.). I doubt that the current restriction on the printf utility not allowing C floating-point literals is intentional. Is there a reason that we should not interpret C floating-point literals (except the passive reason that a non-trivial combination of POSIX statements does not allow it)? I feel it is better to allow the printf implementations to extend the conversion rather than trying to invent strange and inconsistent behaviors among the arithmetic expressions, the arithmetic expansions, and the parameter expansions just to work around the problem. -- Koichi