2016-06-07 32 views
0

我想使用bash運算符+~首先分割一個字符串,然後再次檢查結果字符串。當我嘗試這個,如果發現BASH_REMATCH的元素被第二次使用覆蓋,所以母函數在第二次使用時失敗。如何防止BASH_REMATCH泄漏出某個函數?

就拿下面的構造例如:

#!/bin/bash 

inputline="abc123ABC123abc,xyz890XYZ890xyz" 

checkABC() 
{ 
    local teststring="$1" 
    local pattern="([^,]+),(.*)" 

    if [[ $teststring =~ $pattern ]]; then 
     echo "${BASH_REMATCH[1]}; ${BASH_REMATCH[2]}" 
     checkNum ${BASH_REMATCH[1]} 
     checkNum ${BASH_REMATCH[2]} 
    fi 

} 

checkNum() 
{ 
    if [[ $1 =~ [a-z]+([0-9]+)[A-Z]+([0-9]+)[a-z]+ ]]; then 
     echo "${BASH_REMATCH[1]}; ${BASH_REMATCH[2]}" 
    fi 
} 

set -x 
checkABC $inputline 

這會給下面的輸出,我們可以看到,如何${BASH_REMATCH[2]}由函數checkNum覆蓋。

$ bash ./leaking.sh 
+ checkABC abc123ABC123abc,xyz890XYZ890xyz 
+ local teststring=abc123ABC123abc,xyz890XYZ890xyz 
+ local 'pattern=([^,]+),(.*)' 
+ [[ abc123ABC123abc,xyz890XYZ890xyz =~ ([^,]+),(.*) ]] 
+ echo 'abc123ABC123abc; xyz890XYZ890xyz' 
abc123ABC123abc; xyz890XYZ890xyz 
+ checkNum abc123ABC123abc 
+ [[ abc123ABC123abc =~ [a-z]+([0-9]+)[A-Z]+([0-9]+)[a-z]+ ]] 
+ echo '123; 123' 
123; 123 
+ checkNum 123 
+ [[ 123 =~ [a-z]+([0-9]+)[A-Z]+([0-9]+)[a-z]+ ]] 

我知道我可以防止通過複製複賽的另一個數組,這是我可以在本地處理和應用上checkNum結果(見下面的例子)。這是智能的方式嗎?或者有沒有更好的方法來防止BASH_REMATCH漏出該功能?

此代碼

#!/bin/bash 

inputline="abc123ABC123abc,xyz890XYZ890xyz" 

checkABC() 
{ 
    local teststring="$1" 
    local pattern="([^,]+),(.*)" 
    local -a storeRematch 

    if [[ $teststring =~ $pattern ]]; then 
     storeRematch=("${BASH_REMATCH[@]}") 
     echo "${storeRematch[1]}; ${storeRematch[2]}" 
     checkNum ${storeRematch[1]} 
     checkNum ${storeRematch[2]} 
    fi 

} 

checkNum() 
{ 
    if [[ $1 =~ [a-z]+([0-9]+)[A-Z]+([0-9]+)[a-z]+ ]]; then 
     echo "${BASH_REMATCH[1]}; ${BASH_REMATCH[2]}" 
    fi 
} 

set -x 
checkABC $inputline 

執行像我希望它:

bash ./notleaking.sh 
+ checkABC abc123ABC123abc,xyz890XYZ890xyz 
+ local teststring=abc123ABC123abc,xyz890XYZ890xyz 
+ local 'pattern=([^,]+),(.*)' 
+ local -a storeRematch 
+ [[ abc123ABC123abc,xyz890XYZ890xyz =~ ([^,]+),(.*) ]] 
+ storeRematch=("${BASH_REMATCH[@]}") 
+ echo 'abc123ABC123abc; xyz890XYZ890xyz' 
abc123ABC123abc; xyz890XYZ890xyz 
+ checkNum abc123ABC123abc 
+ [[ abc123ABC123abc =~ [a-z]+([0-9]+)[A-Z]+([0-9]+)[a-z]+ ]] 
+ echo '123; 123' 
123; 123 
+ checkNum xyz890XYZ890xyz 
+ [[ xyz890XYZ890xyz =~ [a-z]+([0-9]+)[A-Z]+([0-9]+)[a-z]+ ]] 
+ echo '890; 890' 
890; 890 
+0

@andlrc我已經嘗試過'local -a BASH_REMATCH'(忘了包含它),它完全打破了比較。 –

回答

1

BASH_REMATCH是一個只讀變量,所以像local BASH_REMATCH工作。

替代正如你提到的自己,你可以將結果複製到另一個變量:

local re 
re=("${BASH_REMATCH[@]}") 

而在你的情況 - 只提它 - 你可以使用:

# teststring="1234,5678" 
checkNum "${teststring%%,*}" # 1234 
checkNum "${teststring#*,}" # 5678 
1

黑客攻擊的一位但由於它只在當前shell的本地,你可以在函數中運行一個子shell。

checkNum() 
{ 
(
    if [[ $1 =~ [a-z]+([0-9]+)[A-Z]+([0-9]+)[a-z]+ ]]; then 
     echo "${BASH_REMATCH[1]}; ${BASH_REMATCH[2]}" 
    fi 
) 
} 

(
checkNum ${BASH_REMATCH[1]} 
checkNum ${BASH_REMATCH[2]} 
) 

這將保持BASH_REMATCH被全局的兩種功能。

除此之外,我認爲將它分配給另一個數組是最好的你會得到(比它更好,因爲它不打開一個新的進程/ subshel​​l)。

相關問題