我有两个脚本可以单独协同工作,但我不知道如何使它们协同工作
任务是使 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
这些错误消息的确切格式可能会有所不同,具体取决于 shell 在您的系统上的作用/bin/sh
。
答案2
你的第一个脚本正在循环$@
,如果你想添加一个操作数,你可以保存第一个参数(op=$1
)然后使用shift
。
从man bash
:
移位[n]
n+1 ... 中的位置参数被重命名为 $1 ...。由数字 $# 到 $#-n+1 表示的参数未设置。 n 必须是小于或等于 $# 的非负数。如果 n 为 0,则不更改任何参数。如果未给出 n,则假定为 1。如果 n 大于 $#,则位置参数不会更改。如果 n 大于 $# 或小于零,则返回状态大于零;否则为 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
而不是循环 and$(( ... )))
为此:
#!/bin/bash
OLDIFS="$IFS"
IFS=$1
shift
bc <<< "scale=5; $*"
IFS=$OLDIFS
"$*"
扩展为单个单词"$1c$2c..."
。通常c
是一个空格,但它实际上是 的第一个字符IFS
,因此它可以是您选择的任何内容。