Странная проблема с printf в сценарии bash:"09" и "08" являются недопустимыми номерами, "07" и " 06 " в порядке
Это мой скрипт bash - я просто хочу оставить набор чисел с нулями:
printf "%04d" "09"
printf "%04d" "08"
printf "%04d" "07"
printf "%04d" "06"
выход:
./rename.sh: line 3: printf: 09: invalid number
0000
./rename.sh: line 4: printf: 08: invalid number
0000
0007
0006
что...?
только 09 и 08 вызывают проблему: каждый другой номер в моей последовательности, кажется, в порядке.
6 ответов
если у вас есть свой "09"
в переменной, вы можете сделать
a="09"
echo "$a"
echo "${a#0}"
printf "%04d" "${a#0}"
почему это поможет? Ну, буквальное число, начинающееся с 0
но не имея x
на 2-м месте интерпретируется как восьмеричное значение.
восьмеричное значение имеют только цифры 0
..7
, 8
и 9
неизвестны.
"${a#0}"
полосы один ведущий 0
. Полученное значение может быть подано в printf
затем, который печатает его соответствующим образом, с 0
префиксальный, в 4 цифры.
если вы должны ожидать, что вы получите ценности, такие как "009"
, все усложняется, так как вам придется использовать цикл, который устраняет все лишнее 0
s в начале, или extglob
выражение, как указано в комментариях.
числа, начинающиеся с "0", рассматриваются как восьмеричные (т. е. база-8). Таким образом, "8" и "9" не являются допустимыми цифрами.
см.http://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic.
Это поведение наследуется от таких языков, как C.
синтаксис числовой арифметической оценки Баша (( ... ))
можно преобразовать в базу 10 (для обеспечения правильной интерпретации) со следующим синтаксисом: (( 10#$var ))
. Или, в случае сырого числа:(( 10#08 ))
. Очень простой и чистый и может использоваться везде, где вы уверены, что база должна быть 10, но не может гарантировать, что ведущий ноль не будет включен.
Итак, в вашем примере это будет следующим образом:
printf "%04d\n" $(( 10#09 ))
printf "%04d\n" $(( 10#08 ))
printf "%04d\n" $(( 10#07 ))
printf "%04d\n" $(( 10#06 ))
производить следующий вывод:
0009
0008
0007
0006
С этот синтаксис, поскольку вы работаете со значением переменной вместо самой переменной, incrementors (( var++ ))
& decrementors (( var-- ))
не будет работать, но все еще может быть сравнительно легко реализован как var=$(( 10#var + 1 ))
и var=$(( 10#var - 1 ))
, соответственно.
Я впервые столкнулся с этим решением здесь, а этот ответ на аналогичный вопрос переполнения стека также демонстрирует это.
просто добавить к Оли!--5-->, для того, чтобы дополнить число нулями достаточно поставить 0
после %
, как:
printf "%04d" "9"
плавающая точка обрабатывается по-разному:
printf "%04.f" "009"
Это дает правильный вывод, не имея дело с какими-либо причудливыми башизмами (в ответе @Oli Charlesworth 0*** рассматривается как восьмеричный, но я считаю, что Bash игнорирует восьмеричные/шестнадцатеричные идентификаторы для чисел с плавающей запятой)
добавлять *
делает расширение параметров оболочки жадным (см., например,Shell Tipps: используйте внутреннюю обработку строк)!
# strip leading 0s
- a="009"; echo ${a##0}
+ a="009"; echo ${a##*0}