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

143 阅读3分钟

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

下面是关于test.sh脚本内容:

#!/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,不过要是后面还有其他的需求,这个逻辑又要修改,对于方案二,则不用修改以前的逻辑,只用追加就行,不用修改以前的逻辑,脚本就不写了,这只是举个栗子。

以上内容希望帮助到大家, 很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家 ,需要戳这里 PHP进阶架构师>>>实战视频、大厂面试文档免费获取