2011-03-09 48 views
10

我一直在閱讀關於bash在這裏和其他地方的報價,但我沒有幫助解決這個問題。與eval,變量和引號bash問題

事情是,我有一個腳本來做循環中的備份。

如果我不使用eval那麼我在rsync中遇到$OPTIONS變量的問題。

但是,如果我不使用eval那麼問題轉到變量$CURRENT_DIR ...

的rsync返回以下消息:「意外的地方ARG:/路徑/與」

我已經想盡引用變量$CURRENT_DIR

CURRENT_DIR="/path/with spaces/backup" 
DIR="dir_by_project" 
f=":/home/project_in_server" 
OPTIONS="-avr --exclude 'public_html/cms/cache/**' --exclude 'public_html/cms/components/libraries/cmslib/cache/**' --delete" 
eval rsync --delete-excluded -i $OPTIONS [email protected]$f $CURRENT_DIR/xxx/$DIR/files 

的方式是沒有辦法,我可以使用變量$CURRENT_DIR不會因空間問題什麼辦法?

回答

13
eval rsync --delete-excluded -i $OPTIONS [email protected]$f "\"$CURRENT_DIR/xxx/$DIR/files\"" 

command "some thing"執行命令的一個參數就some thing。引號由shell解析,參數在執行命令時設置爲數組。該命令將看到一個參數爲某件事沒有引號。

eval命令或多或少地將它們的參數視爲輸入到shell中。所以,如果你eval command "some thing",bash執行eval有兩個參數:commandsome thing(同樣,bash設置參數數組時引用了引號)。所以,eval的行爲就好像你在shell中輸入了command some thing,這不是你想要的。

我所做的只是逃避引號,這樣的bash通過字面「一些事」包括引號EVAL。 eval然後就好像你輸入了command "some thing"一樣。

我的命令中的外部引號不是嚴格要求的,它們只是習慣。您也可以使用:

eval rsync --delete-excluded -i $OPTIONS [email protected]$f \"$CURRENT_DIR/xxx/$DIR/files\" 
+0

它的工作,但我不知道爲什麼?我想這與分詞有關。你能否在你的回答中多說一點? [編輯]我想我現在明白了。我使用了eval,因爲我希望$ OPTIONS被分割,並且CURRENT_DIR也被分割了。當eval運行時,首先刪除引號... – Cesar 2011-03-10 00:21:00

+0

感謝您的澄清! – Cesar 2011-03-10 00:31:23

0

我知道大概ypu已經用過了,但是,單引號呢? (這個類型 ' ' ) ?

-1

你需要CURRENT_DIR="/path/with\ spaces/backup"逃生空間,如果這不工作,那麼把雙反斜線CURRENT_DIR="/path/with\\ spaces/backup"

+1

這可能會解決這個問題,但通常不是一個好的解決方案......問題中定義的變量的值是正確和合理的。 – 2011-03-10 00:02:21

7

使用eval是危險的,應該儘可能避免使用eval。在這種情況下,主要問題是您試圖將OPTIONS定義爲包含多個單詞,而bash變量不能很好地處理這個問題。有一個解決方案:將OPTIONS放入一個數組中,而不是一個簡單的變量(並且在所有變量引用周圍使用雙引號,以防止將空格視爲單詞分隔符)。

CURRENT_DIR="/path/with spaces/backup" 
DIR="dir_by_project" 
f=":/home/project_in_server" 
OPTIONS=(-avr --exclude 'public_html/cms/cache/**' --exclude 'public_html/cms/components/libraries/cmslib/cache/**' --delete) 
rsync --delete-excluded -i "${OPTIONS[@]}" "[email protected]$f" "$CURRENT_DIR/xxx/$DIR/files" 
+0

+1表示清楚的解釋。我只想知道,這種解決方案有多便攜。我嘗試在OS X 10.5中,它的工作,但它會在其他操作系統的工作?這個工作所需的最低bash版本是什麼? – Cesar 2011-03-10 20:07:22

+0

@Cesar:根據[this](http://lcorg.blogspot.com/2010/04/new-features-in-bash-version-4x-part-4.html),線性數組(I' m在這裏使用)被添加到bash v2中。 (關聯數組在bash v4中是新的,但在這裏不需要。) – 2011-03-10 22:49:30

3

我與戈登

同意你在這種情況下沒有必要的eval(你是不是從變量形成一個變量名,或以其他方式在運行一個表達式)

而且和你想雙引號所有可能引用可能有空間,你想保存

但另一個好習慣是總是用{}來引用變量...

"${CURRENT_DIR}" 

代替

$CURRENT_DIR 

這消除了任何名含糊不清