개별적으로 함께 작동하는 두 개의 스크립트가 있지만 함께 작동하게 만드는 방법을 모르겠습니다.
임무는 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
...
( '*'
파일 이름으로 확장되지 않도록 따옴표로 묶어야 합니다.)
그러나 나는 루프 대신 bc
and를 사용하고 싶습니다 .$IFS
$(( ... )))
#!/bin/bash
OLDIFS="$IFS"
IFS=$1
shift
bc <<< "scale=5; $*"
IFS=$OLDIFS
"$*"
단일 단어로 확장합니다"$1c$2c..."
. 이는 일반적으로c
공백이지만 실제로는 의 첫 번째 문자이므로IFS
원하는 대로 지정할 수 있습니다.