Bash에서 역방향 표기법의 더 나은 구현

Bash에서 역방향 표기법의 더 나은 구현

나는 Bash에서 "역 부호" 기능을 더 잘 구현하는 데 관심이 있습니다. 나는 다음과 같은 일을 할 수 있다는 것을 알고 있습니다.

"$(($1 * -1))"

하지만 이는 부호 없는 양수를 생성하지만 부호 있는 반환 값이 필요합니다.

"$((-1 * -1))" == 1 # but I need '+1'

내 현재 버전은 다음과 같습니다

# Reverts the +/- operators for an integer argument.
#
#   $ polarize -1   # +1
#   $ polarize +12  # -12
#   $ polarize 2-2  # 2-2
#   $ polarize - 1  # - 1
#
function polarize() {
  [ $# -eq 0 ] && return

  if [[ "$@" =~ ^-([[:digit:]]+)$ ]]; then
    echo -n "+${BASH_REMATCH[1]}"
  elif [[ "$@" =~ ^\+([[:digit:]]+)$ ]]; then
    echo -n "-${BASH_REMATCH[1]}"
  else
    echo -n "$@"
  fi
}

몇 가지 참고사항:

  • 함수는 부호 있는 정수만 처리해야 합니다(예: -1, +22, 그러나 0OR 는 아님 100).
  • 매개변수가 없으면 함수는 아무것도 반환하지 않아야 합니다.
  • 함수는 여러 인수를 올바르게 처리해야 합니다(아무 작업도 수행하지 않음).

답변1

사용 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주의하고 8진수( 에서와 같이 로 시작하여 작성됨)를 유효한 정수로 허용하지 않으려면 034정규 표현식을 다음으로 변경하세요.

^[+-][1-9][[:digit:]]*$

답변2

정규식을 사용하고 있으므로 더 좋게 만들 수도 있습니다.

^-([[:digit:]]+)$기호가 아닌 숫자만 캡처 하면 됩니다 .

  • 두 플래그 중 하나를 캡처하려면 정규식을 다음과 같이 변경하면 됩니다.

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

    기호 ( +또는 -) 는 다음과 같습니다.아니요선택사항(?), 반드시 존재해야 합니다(귀하의 요구사항에 따라).

  • 008과 같은 선행 0을 제거하지 마십시오. 오류가 발생합니다.

    008: 잘못된 8진수

    로 변경:

    ^([+-])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>

관련 정보