2012-03-03 75 views
3

我有一個複雜的腳本,從文件需要的變量,並用它們來運行程序(特別是紅酒)傳遞標誌,以通過變量命令在bash

傳遞從變量選項中的其他文件無法正常運行:

#!/bin/bash 
. settingsfile 
wine $run 

而在其他文件中:

run="run.exe -withoption \"This text\"" 

當我改變wine $runecho wine $run,它回聲一個字符串,WH當明確運行ICH正常工作:

#!/bin/bash 
. settingsfile 
wine run.exe -withoption "This text" 

編輯:#!/bin/bash -x運行顯示我:

+ wine run.exe -withoption '"This' 'text"' 

我該如何解決這個問題?

+0

真奇怪。它*應該*按原樣工作。嘗試將shebang行更改爲'#!/ bin/bash -x'以更好地瞭解如何執行擴展。 – 2012-03-03 15:52:10

+0

這是一個很棒的選擇,謝謝!它顯示它沒有明顯的原因被包裹在單引號中...... – 2012-03-03 16:00:58

回答

7

問題是"Thistext"被視爲單獨的參數,每個參數都包含雙引號而不是單個參數This text。如果你寫一個函數來打印每行一個參數,你可以看到這個;此:

function echo_on_separate_lines() 
{ 
    local arg 
    for arg in "[email protected]" ; do 
    echo "<< $arg >>" 
    done 
} 
run="run.exe -withoption \"This text\"" 
echo_on_separate_lines $run 

打印這樣的:

<<run.exe>> 
<< -withoption >> 
<< "This >> 
<< text" >> 

而不是這樣的:

<<run.exe>> 
<< -withoption >> 
<< This text >> 

的最簡單的解決方案是釘在一個eval重新處理的引用:

run="run.exe -withoption \"This text\"" 
wine $run  # or better yet: wine "$run" 

但是a更強大的解決方案是讓run是一個數組,然後你就可以稱其爲"${run[@]}"

run=(run.exe -withoption "This text") 
wine "${run[@]}" 

從而使報價從妥善處理得到去。

+0

很好的解釋,但是除了數組之外,還有其他方法嗎?或者是否可以在運行之前正確地將字符串轉換爲數組? – 2012-03-03 16:03:35

+1

@JV:我猜你看到我的答案的一個版本,然後我編輯它提到'eval'?那麼,它現在提到'eval',這是除了數組之外的另一種方式。但是我認爲如果可以的話,數組是最安全和最穩健的方式。 – ruakh 2012-03-03 16:08:45

+0

我可以做一個數組,但這對於'$ run'是單個文件的情況來說很煩人。 'eval'正是我要找的,謝謝! – 2012-03-03 16:14:46

5

簡短的回答:看BashFAQ #050: I'm trying to put a command in a variable, but the complex cases always fail!

龍答:把引號的變量沒有做什麼有用的,因爲bash的解析報價它將替換變量與他們的價值觀之前;這意味着當它被替換$runrun.exe -withoption "This text"它已經完成報價解析,並且不會回頭並注意那些雙引號,這意味着他們沒有做你期望的。

BTW,使用echo檢查發生的事情是極其錯誤的,因爲echo向您展示了它的參數看起來像他們解析後,但你讀它,就好像這是他們展示之前解析。相反,使用@ Eduardo的-x建議來看看到底發生了什麼。 (順便說一下,您還可以使用set -x爲腳本的有趣部分啓用此功能,然後使用set +x將其關閉。)

那麼你如何解決它?一般來說,最好的辦法是把一個數組,而不是一個簡單的變量您的命令,然後使用成語"${arrayname[@]}"到每個數組元素傳遞作爲單獨的參數:

run=(run.exe -withoption "This text") 
wine "${run[@]}"