스크립팅을 위한 Bash 연산자

스크립팅을 위한 Bash 연산자

개별적으로 함께 작동하는 두 개의 스크립트가 있지만 함께 작동하게 만드는 방법을 모르겠습니다.

임무는 bash 스크립트가 연산자와 정수 목록을 받아들이고 명령이 작업을 수행하도록 하는 것입니다.

기본적으로 스크립트를 사용할 수 있어야 합니다.

test.sh add 1 2 3
5
test.sh sub 4 2 1
1

내 첫 번째 스크립트는

for var in $@
do

sum=$(( sum + var ))
done
echo $sum

두 번째 스크립트는

if [ $operator = add ]; then
add= echo $(($a+$b))

elif 

답변1

스크립트는 첫 번째 명령줄 인수를 별도의 변수로 선택한 op다음 명령줄 인수 목록에서 제거합니다.

#!/bin/sh

op=$1
shift

이 스크립트를 add 1 2 3인수로 사용하여 호출하면 코드는 문자열을 add에 할당하고 로 op유지합니다 .1 2 3"$@"

그런 다음 나머지 명령줄 인수를 반복할 수 있습니다.

#!/bin/sh

op=$1
shift

for arg do
    # some commands should go here
done

추가된 루프는 변수가 arg나머지 각 명령줄 인수의 값을 차례로 취하도록 보장합니다. 이와 같이 루프의 시작 부분을 작성할 수도 있지만 for arg in "$@"; do ...더 많은 입력이 필요하고 프로그래머는 때때로 주위에 따옴표를 추가하는 것을 잊어버립니다 $@.

값에 따라 $op루프 내에서 여러 작업 중 하나가 발생할 수 있습니다. 우리는 $op그것이 무엇인지 확인하고 올바른 일을 하기 위해 간단한 테스트를 할 수 있습니다 . 어쨌든 아래에 일부 값이 누적되고 acc해당 acc값은 (질문에 명령이 표시되는 방식에 따라) 첫 번째 숫자로 초기화되어야 하며 해당 숫자도 매개변수 목록에서 제거해야 합니다.

#!/bin/sh

op=$1
shift

acc=$1
shift

for arg do
    case $op in
        add) acc=$(( acc + arg )) ;;
        sub) acc=$(( acc - arg )) ;;
        mul) acc=$(( acc * arg )) ;;
        div) acc=$(( acc / arg )) ;; # note: integer division here
        *)
            printf 'Unknown operation: %s\n' "$op" >&2
            exit 1
    esac
done

printf '%s\n' "$acc"

스크립트를 저장하고 실행 가능하게 만든 후 테스트합니다.

$ ./script add 1 2 3
6
$ ./script sub 4 2 1
1
$ ./script xor a b c
Unknown operation: xor
$ ./script add
script[7]: shift: nothing to shift

마지막 두 번의 호출에 주목하세요. 마지막 것은 숫자를 제공하지 못하므로 두 번째는 shift실패합니다. 두 번째 호출은 작업이 알 수 없음을 알리고 조기 종료됩니다.

op할당 과 초기화를 약간 변경하면 acc오류 메시지를 좀 더 유용하게 만들 수 있습니다.

#!/bin/sh

op=${1:?Expected operator}
shift

acc=${1:?Expected number}
shift

for arg do
    case $op in
        add) acc=$(( acc + arg )) ;;
        sub) acc=$(( acc - arg )) ;;
        mul) acc=$(( acc * arg )) ;;
        div) acc=$(( acc / arg )) ;; # note: integer division here
        *)
            printf 'Unknown operation: %s\n' "$op" >&2
            exit 1
    esac
done

printf '%s\n' "$acc"

다시 테스트하세요:

$ ./script
script[3]: 1: Expected operator
$ ./script add
script[6]: 1: Expected number
$ ./script add 1 2
3

이러한 오류 메시지의 정확한 형식은 시스템에서 쉘의 역할에 따라 달라질 수 있습니다 /bin/sh.

답변2

첫 번째 스크립트는 반복됩니다 $@. 피연산자를 추가하려면 첫 번째 매개변수( op=$1)를 저장한 다음 를 사용하면 됩니다 shift.

에서 man bash:

시프트[n]
n+1 ...의 위치 매개변수 이름이 $1 ...로 변경되었습니다. $#부터 $#-n+1까지의 숫자로 표시되는 매개변수는 설정되지 않습니다. n은 $#보다 작거나 같은 음수가 아닌 숫자여야 합니다. n이 0이면 매개변수가 변경되지 않습니다. n을 지정하지 않으면 1로 가정됩니다. n이 $#보다 크면 위치 매개변수가 변경되지 않습니다. n이 $#보다 크거나 0보다 작으면 반환 상태는 0보다 크고, 그렇지 않으면 0입니다.

$result첫 번째 인수로 초기화한 후 shift다시 사용하세요.

또한 $@루프를 실행할 때 반드시 인용문을 사용하세요(읽다여기).

#!/bin/bash
op=$1
shift
result=$1
shift
for var in "$@"; do
  result=$(( result $op var ))
done
echo "$result"

shift한 단계로 수행 할 수도 있습니다 .

op=$1
result=$2
shift 2

달리 test.sh + 1 2 3거나 test.sh '*' 1 2 3...

( '*'파일 이름으로 확장되지 않도록 따옴표로 묶어야 합니다.)


그러나 나는 루프 대신 bcand를 사용하고 싶습니다 .$IFS$(( ... )))

#!/bin/bash
OLDIFS="$IFS"
IFS=$1
shift
bc <<< "scale=5; $*"
IFS=$OLDIFS

또한보십시오:

"$*"단일 단어로 확장합니다 "$1c$2c...". 이는 일반적으로 c공백이지만 실제로는 의 첫 번째 문자이므로 IFS원하는 대로 지정할 수 있습니다.

관련 정보