Улучшенная реализация обратного знака в Bash

Напоминание о том, что репозитории CentOS, вероятно, все еще будут существовать.

Тот факт, что у вас будет пара старых выпусков, тот факт, что не будет никаких обновлений безопасности, вы можете учитывать.

8 скоро должны выйти.

0
24.04.2020, 09:19
2 ответа

Используйтеprintf:

printf '%+d\n' "$(( -$n ))"

Строка формата printf%+dозначает «печатать данный аргумент как десятичное целое число со знаком».

Таким образом, вы получите что-то вроде

revsign () {
    if [ "$#" -eq 1 ] && [[ $1 =~ ^[+-][[:digit:]]+$ ]]; then
        printf '%+d\n' "$(( -$1 ))"
    fi
}

Это ничего не делает, если задано несколько аргументов или если задан один аргумент, который не является целым числом со знаком.

Для прохождения через аргументы, когда их несколько или когда единственный аргумент не является целым числом со знаком:

revsign () {
    if [ "$#" -eq 1 ] && [[ $1 =~ ^[+-][[:digit:]]+$ ]]; then
        printf '%+d\n' "$(( -$1 ))"
    elif [ "$#" -gt 0 ]; then
        printf '%s\n' "$@"
    fi
}

Если вы хотите быть осторожным и не принимать восьмеричные числа (, записанные с начальным 0, как в 034), как допустимые целые числа, измените регулярное выражение на

^[+-][1-9][[:digit:]]*$
6
19.03.2021, 02:26

Поскольку вы используете регулярное выражение, вы можете сделать его лучше.

Простой ^-([[:digit:]]+)$будет захватывать только цифры, а не знак, и:

  • Чтобы получить любой знак, просто измените регулярное выражение на:

    ^([+-])([0-9]+)$
    

    Обратите внимание, что знак(+или-)является не необязательным (? ), он должен существовать (в соответствии с вашими требованиями ).

  • Не удалять ведущие нули, как в 008, что вызовет ошибку:

    008: invalid octal number

    Измените на:

    ^([+-])0*([0-9]+)$
    
  • Из вашего описания неясно, разрешены ли пробелы и/или табуляции, если да, измените на:

    ^[[:blank:]]*([+-])0*([0-9]+)$
    

Тогда правильное число может быть заново -построено из:

${BASH_REMATCH[1]}${BASH_REMATCH[2]}

Или просто:

${BASH_REMATCH[@]:1:2}

Весь сценарий станет примерно таким:

#! /bin/bash

# Reverts the +/- operators for an integer argument.
#
#   $ polarize -1   # +1
#   $ polarize +12  # -12
#   $ polarize 2-2  # 2-2
#   $ polarize - 1  # - 1
#
polarize () {
    re='^[[:blank:]]*([+-])0*([[:digit:]]+)$'

    [[ $# -ne 1  ]] && return
    [[ $1 =~ $re ]] || return

    printf '<%+d>' "$(( -${BASH_REMATCH[@]:1:2} ))"
}

for n; do
    printf '%s' "testing ==$n=="
    polarize "$n"
    echo
done

И при выполнении (список значений действителен для всего скрипта только для проверки, функция принимает только один аргумент)(нет вывода для 0, 100 и некоторых других тестов):

$./testbash.sh +1 -1 +22 -12 0 100 2-2 "- 1" +008
testing ==+1==<-1>
testing ==-1==<+1>
testing ==+22==<-22>
testing ==-12==<+12>
testing ==0==
testing ==100==
testing ==2-2==
testing ==- 1==
testing ==+008==<-8>
0
19.03.2021, 02:26

Теги

Похожие вопросы