PHP傳遞陣列格式引數到shell指令碼中

2020-07-16 10:05:35

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 [email protected]
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 [email protected]
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指令碼,嗯,就這醬紫(emmmmm……指令碼未做容錯處理)……


再補充學到的幾個簡單的命令,不能忘了……
1 dos2unix 將Windows下檔案中的換行鍵轉換成Unix下的換行鍵(可使用Notepad++編輯器看到window下為換行符為CR LF,unix下的換行符為LF)
2 sort 對檔案按照指定規則進行排序
3 comm 將兩個有序檔案進行對比,可以取到差集、交集(功能很強大,然後兩個檔案必須是有序的,不然會報錯,也就是上個sort命令排序過的檔案)
4 wc 統計檔案行數(其實就是統計換行符)
5 [email protected] 指令碼的所有引數
6 $# 指令碼引數個數
7 ${@:1:4} 指代指令碼引數從1開始至第4個(可以範圍選擇)

更多PHP相關技術文章,請存取PHP教學欄目進行學習!

以上就是PHP傳遞陣列格式引數到shell指令碼中的詳細內容,更多請關注TW511.COM其它相關文章!