PHP传递数组格式参数到shell脚本中

4次阅读

共计 2994 个字符,预计需要花费 8 分钟才能阅读完成。

PHP 中传递类似于“数组”格式数据到 shell 脚本中:
模拟场景 1:计算捆绑商品的价格,捆绑商品中包含多个商品,这个商品是不确定的,我们暂时定义为苹果、栗子、香蕉,价格分别为 8 元 / 斤、10 元 / 斤、3 元 / 斤,重量规格定为 500g,我们把价格当做参数传递给 shell 脚本计算总价格
以下是关于 PHP 部分的代码:

$prices = array(
    "apple"    => 8,
    "banana"   => 3,
    "chestnut" => 10
);

$command = "bash".ROOT_PATH."/script/test.sh";
foreach ($prices as $price) {$command .= $price." ";}
$output = array();
$ret = 1;
exec($command."2>&1", $output, $ret);
var_dump($command, $output, $ret);exit;
// command 命令为:// bash /data/home/tina/script/test.sh 8 3 10

下面是关于 shell 脚本内容:

#!/bin/bash

all=0
for price in $@
do
    all=`expr ${all} + ${price}`
done
echo ${all}

场景 2:在场景 1 的情况下,我们修改价格为浮点数,苹果、栗子、香蕉价格分别为 8.8 元 / 斤、9.9 元 / 斤、3.5 元 / 斤,expr 表达式会报错(expr: 参数数目错误),expr 不支持浮点类型,这里应该采用 bc 或者 awk,shell 脚本修改如下:

#!/bin/bash

all=0
for price in $@
do
    #all=$(echo ${price}+${all}|bc)
    all=$(awk "BEGIN{print ${all}+${price}}")
done
echo ${all}

场景 3:在场景 2 的基础上,捆绑商品现在需要变更重量,苹果 0.5KG、香蕉 1KG、栗子 1.5KG,则计算价格时,我们也需要把重量的参数传递到 shell 脚本中,才能计算价格。
方案一:继续把这些参数加在脚本之后,把参数个数一分为二,我们知道前面一半部分为价格参数,后半段参数为重量参数,修改如下:
PHP 代码部分:

$prices = array(
    "apple"    => 8.8,
    "banana"   => 3.5,
    "chestnut" => 9.9
);
$weights = array(
    "apple"    => 1,
    "banana"   => 2,
    "chestnut" => 3
);

$command = "bash".ROOT_PATH."/script/test.sh";
foreach ($prices as $price) {$command .= $price." ";}
foreach ($weights as $weight) {$command .= $weight." ";}

$output = array();
$ret = 1;
exec($command."2>&1", $output, $ret);
var_dump($command, $output, $ret);exit;
// command 命令为:// bash /data/home/tina/script/test.sh 8.8 3.5 9.9 1 2 3 

修改的 shell 脚本为:

#!/bin/bash

all=0
count=`expr ${#} / 2`
countIndex=`expr ${count} + 1`

for price in ${@:1:${count}}
do
    #all=$(echo "${price}*${!countIndex}+${all}"|bc)
    all=$(awk "BEGIN{print ${all}+${price}*${!countIndex}}")
    countIndex=`expr ${countIndex} + 1`
done
echo ${all}

方案二:把这两种数据进行分组,就类似于 PHP 的数组一样,这样需要在命令中将每组参数分别用单引号包裹,这样 shell 则会认为只有两个参数,再在 shell 脚本中当做数组来处理,修改如下:
PHP 部分:

$prices = array(
    "apple"    => 8.8,
    "banana"   => 3.5,
    "chestnut" => 9.9
);
$weights = array(
    "apple"    => 1,
    "banana"   => 2,
    "chestnut" => 3
);

$command = "bash".ROOT_PATH."/script/test.sh'"; // 添加单引号
foreach ($prices as $price) {$command .= $price." ";}
$command = trim($command) . "''";  // 添加单引号
foreach ($weights as $weight) {$command .= $weight." ";}
$command = trim($command) . "'";  // 添加单引号
$output = array();
$ret = 1;
exec($command."2>&1", $output, $ret);
var_dump($command, $output, $ret);exit;
// command 命令为:// bash /data/home/tina/script/test.sh '8.8 3.5 9.9' '1 2 3'

shell 脚本修改为:

#!/bin/bash

all=0
index=0
prices=(${1})
weights=(${2})

for price in ${prices[@]}
do
    all=$(awk "BEGIN{ print ${price}*${weights[${index}]}+${all} }")
    index=`expr ${index} + 1`
done
echo $all

对比于方案一和方案二,从长远看,个人认为还是方案二占优势一些,易于区分:可以明显知道第一个参数是价格组,第二个参数是重量组,可扩展:例如后续还要增加一个折扣率的参数(折扣率分别为 0.9、0.88、0.95),优惠券减价 5 元等;
对于方案一,这个 count 的值是不固定的,折扣率计算的话,假定每个水果种类都有单独的折扣率,则这个 count 还是 3 的倍数,把除以 2 修改为除以 3 就可以

#command 命令为:bash /data/home/tina/script/test.sh 8.8 3.5 9.9 1 2 3 0.9 0.88 0.95

但是对于优惠券来说,那肯定是对这个捆绑商品的整体优惠了,就是单独的一个参数,假定优惠券为 5 元,继续追加参数

#command 命令为:bash /data/home/tina/script/test.sh 8.8 3.5 9.9 1 2 3 0.9 0.88 0.95 5

这个时候也已经不好区分了,一连串数字,不利于后续维护,接手的人肯定一脸懵逼,这都是些什么参数啊,然后内心开始一阵吐槽,方案一想想办法也能修改 count=(参数个数 -1)/3,不过要是后面还有其他的需求,这个逻辑又要修改,很烦额,对于方案二,则不用修改以前的逻辑,只用追加就行,不用修改以前的逻辑。

其实,由于工作需要,才接触到要写 shell 脚本,初次看到一脸懵逼,这个场景也是模拟的,实际上是要对大批量的大文件进行处理,然后边学边看,发现这些命令超级……怎么说呢?感觉就像发现了新大陆

记录第一次写 shell 脚本,嗯,就这酱紫……
后续再补充学到的几个简单的命令,不能忘了……

正文完
 0