2010-06-07 29 views
4

我想自動執行以下svn命令。注意此命令產生我的系統上所期望的結果 - 的Ubuntu 10.04,SVN 1.6.6,bash shell中,在命令行發行時:幫助變量和換行符,並在bash腳本中引用

svn ci -m $'Added new File: newFile.txt\nOrig loc: /etc/networking/newFile.txt' /home/user/svnDir/newFile.txt 

我想在bash腳本運行命令,假設文件的原始完整路徑包含在變量$ oFileFull中,文件名在$ oFileName中。該腳本從svn目錄執行。我需要考慮到文件名和或路徑包含空格的可能性。

所以我SHEL腳本中的行可能看起來像:

svn ci -m$'Added new file: ${oFileName}\nOrig loc: ${oFileFull}' ${oFileName} 

但我想在執行命令前的變量(可以包含空格)擴展,我無法弄清楚如何做到這一點的同時將svn註釋括在單引號中,這是爲了在subversion註釋日誌中獲得新行而必需的。我拉着我的頭髮試圖弄清楚如何正確引用和組裝這個命令。任何幫助讚賞。

回答

4

將你的換行符放在一個變量中,在需要換行符的地方使用變量,並將你的大字符串中的引號改爲雙引號。你也應該總是引用任何包含文件名的變量。

nl=$'\n' 
svn ci -m"Added new file: ${oFileName}${nl}Orig loc: ${oFileFull}" "${oFileName}" 
+0

謝謝 - 工作就像一個魅力。 奇怪的是,當試驗和使用echo來顯示輸出時,$ nl變量必須用雙引號而不是單引號來聲明。 單引號適用於svn命令,日誌格式正確。 – Scott 2010-06-07 18:10:56

+0

@Scott:'nl = $'\ n';回聲「一個$ {nl}兩個」'應該工作。在這種情況下,使用'nl = $「\ n」'與'nl =「\ n」'相同,並且需要'echo -e'來解釋文字「\ n」(兩個字符:反斜槓-n),除非你的'echo'版本一直都用'-e'。 「回聲」一個\ nb「'與'echo -e」a \ nb「相比有什麼用處? – 2010-06-07 19:13:29

+0

echo「a \ nb」= a \ nb echo -e「a \ nb」= a在一行後接b在下一行 – Scott 2010-06-07 19:57:01

0

@Dennis:

哇,這是很難繞到我的頭,我喜歡它,如果有人能指出我朝着一個在線資源,清楚,簡要地解釋了這一點。我發現的那些人沒有爲我清理它。

我最近混亂的根源是:

#!/bin/bash 
nl=$'\n' 
msg="Line 1${nl}Line 2" 
echo $msg  # ouput = Line 1 Line 2 
echo -e $msg  # ouput = Line 1 Line 2 
echo "$msg"  # output = Line 1 
       # Line 2 

什麼我試圖說明的是,周圍具有變量$味精雙引號拆分輸出轉換成兩行,如果沒有雙引號,即使使用-e開關,也沒有新的線路。

我不明白爲什麼雙引號是必要的 - 爲什麼當$ nl變量被指定爲msg變量的一部分時不擴展?

我希望我沒有通過回答我自己的問題來提交StackOverflow錯誤。事實上,我並沒有真正提供答案,而僅僅是對你評論的迴應。我不能根據需要格式化評論。

+0

$ nl變量*被分配給$ msg時被擴展。但請參閱我的其他冗長的回答,瞭解爲什麼echo會在您的示例中執行它的功能。 (可能會犯我自己的失禮,但我不能在評論中給出完整的答案。) – 2010-06-07 22:10:25

7

@Scott,我知道這已經被回答了,但這裏有一些關於echo $ msg和echo「$ msg」區別的附加問題的評論。你的例子:

nl=$'\n' 
msg="Line 1${nl}Line 2" 
echo $msg  # ouput = Line 1 Line 2 
echo -e $msg  # ouput = Line 1 Line 2 
echo "$msg"  # output = Line 1 
       # Line 2 

它確實有助於瞭解shell在每種情況下傳遞給echo命令的參數。 Echo可以使用任意數量的參數。它將它們全部寫入標準輸出,按順序寫入,除了最後一個之外,每個之後都有一個空格。

在第一個例子,回聲$味精,外殼替換$味精是由於您將其設置爲(其中一個是一個換行符)的字符。調用回波之前然後它分裂該字符串轉換成使用內部字段分隔符(IFS)多個參數,並將它傳遞的是所得的參數列表呼應。默認情況下,IFS被設置爲空格(空格,製表符和換行符),因此shell將$ msg字符串轉換爲四個參數:「Line」,「1」,「Line」和「2」。回聲甚至從來沒有看到換行符,因爲外殼認爲它是一個分隔符,就像空間一樣。

在第二個示例echo -e $ msg中,echo命令接收五個參數:「-e」,「Line」,「1」,「Line」,「2」。 -e參數告訴命令展開它在參數中看到的任何反斜槓字符,但沒有,所以echo保留參數不變。結果與第一個例子相同。

在最後一個例子,回聲「$味精」,你告訴shell來擴展$msg,並通過其內容呼應對待雙引號之間的一切作爲一個參數,所以回聲接收一個參數,一個包含字母,數字,空格和換行符的字符串。它完全按照它接收到的那樣迴響該字符串,因此「第1行」和「第2行」出現在單獨的行上。

試試這個實驗:將IFS設置爲任意的東西,像字母i和觀看外殼多麼不同將您的字符串:

nl=$'\n' 
msg="Line 1${nl}Line 2" 
IFS=i 
echo $msg  # ouput = L ne 1 
       # L ne 2 

也沒什麼可說的空白特別神奇。在這裏,因爲怪異的IFS,shell將字母i作爲分隔符,而不是空格或換行符。所以echo收到三個參數:「L」,「ne \ nL」和「ne 2」。 (我將換行符顯示爲\ n,但它實際上只是單個字符,如X或p或5.)

一旦您意識到shell的命令行中的單引號和雙引號都是關於構造這些命令的參數,邏輯開始有意義。

+0

謝謝 - 非常有幫助。 – Scott 2010-06-08 00:02:37

0

Bash將連接相鄰的引用段。因此,例如

$ r=rooty 
$ t=tooty 
$ echo $r$'\n'$t 
rooty 
tooty 
$ echo "$r $r"$'\n'$t 
rooty rooty 
tooty 

對於在線指南,先進的bash腳本指南可能是有用的,儘管它可能是沒有不僅僅是閱讀bash的長長的詳細說明書更好。我建議使用vim的Man命令(7.2版本的標準,如果不是早期版本的話)調出bash手冊,然後使用基於縮進的摺疊,以便瀏覽它的層次結構。那麼,假設你沒有時間和耐心從頭到尾閱讀所有3300行。