PHP中传递相似于“数组”格式数据到shell脚本中:shell
计算捆绑商品的价格,捆绑商品中包含多个商品,这个商品是不肯定的,咱们暂时定义为苹果、栗子、香蕉,价格分别为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脚本内容:bash
#!/bin/bash all=0 for price in $@ do all=`expr ${all} + ${price}` done echo ${all}
在场景1的状况下,咱们修改价格为浮点数,苹果、栗子、香蕉价格分别为8.8元/斤、9.9元/斤、3.5元/斤,expr表达式会报错(expr: 参数数目错误),expr不支持浮点类型,这里应该采用bc或者awk,shell脚本修改以下:app
#!/bin/bash all=0 for price in $@ do #all=$(echo ${price}+${all}|bc) all=$(awk "BEGIN{print ${all}+${price}}") done echo ${all}
在场景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脚本为:unix
#!/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部分:code
$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.九、0.8八、0.95),优惠券减价5元等;
对于方案一,这个count的值是不固定的,折扣率计算的话,假定每一个水果种类都有单独的折扣率,则这个count仍是3的倍数,把除以2修改成除以3就能够ip
#command命令为: bash /data/home/tina/script/test.sh 8.8 3.5 9.9 1 2 3 0.9 0.88 0.95
可是对于优惠券来讲,那确定是对这个捆绑商品的总体优惠了,就是单独的一个参数,假定优惠券为5元,继续追加参数it
#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脚本,嗯,就这酱紫(emmmmm……脚本未作容错处理)……
再补充学到的几个简单的命令,不能忘了……
1 dos2unix
将Windows下文件中的换行键转换成Unix下的换行键(可以使用Notepad++编辑器看到window下为换行符为CR LF,unix下的换行符为LF)
2 sort
对文件按照指定规则进行排序
3 comm
将两个有序
文件进行对比,能够取到差集、交集(功能很强大,而后两个文件必须是有序的,否则会报错,也就是上个sort命令排序过的文件)
4 wc
统计文件行数(其实就是统计换行符)
5 $@
脚本的全部参数
6 $#
脚本参数个数
7 ${@:1:4}
指代脚本参数从1开始至第4个(能够范围选择)