我試圖從 shell 腳本中理解這一行。我知道這$(..)
意味著運行並將其輸出插入到語句中..
找到的位置。$()
但是這些括號之間發生了什麼事?這是做什麼的\ls
?\
這是\\
兩條線的分割嗎?\ls
和普通的一樣嗎ls
?
APPCLASSPATH=$CLASSPATH:$({ \
\ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \
\ls -1 "$VOLTDB_LIB"/*.jar; \
\ls -1 "$VOLTDB_LIB"/extension/*.jar; \
} 2> /dev/null | paste -sd ':' - )
答案1
3 個命令的輸出ls
將傳遞到將paste
它們合併到值中的命令:
$VOLTDB_VOLTDB"/voltdb-*.jar:$VOLTDB_LIB"/*.jar:$VOLTDB_LIB"/extension/*.jar
筆記:變數$VOLTDB_VOLTDB
和$VOLTDB_LIB
將被擴展,並且每個ls
命令可能有多個值,而不僅僅是一個檔案。看到*
那裡了嗎?這是一個通配符,可擴展為左側 (voltdb-) 和右側 (.jar) 之間的任何內容。
這些將匹配:
voltdb-1.jar
voltdb-blah.jar
voltdb-12345.jar
然後所有內容都包含在變數中APPCLASSPATH
:
APPCLASSPATH=$CLASSPATH:$VOLTDB_VOLTDB"/voltdb....etc.
貼上命令
seq
下面是我使用指令產生數字序列 1-10 的範例。
$ seq 10 | paste -sd ':' -
1:2:3:4:5:6:7:8:9:10
您可以看到該paste
指令正在合併輸出並以冒號 ( :
) 分隔。
您也可以像這樣模仿範例命令:
$ { echo "hi1"; echo "hi2"; echo "hi3"; } | paste -sd ':' -
hi1:hi2:hi3
筆記:to -
the Past 命令告訴它從 STDIN 獲取輸入並列印輸入的每個參數,以:
.
透過不同的開關,paste
還可以根據-
資料後面的數量將資料分成組。
貼上範例
這是一個帶有 2-
的範例。
$ seq 10 | paste - -
1 2
3 4
5 6
7 8
9 10
這是 3-
的。
$ seq 10 | paste - - -
1 2 3
4 5 6
7 8 9
10
所以它告訴每行應該要列印paste
多少個參數。paste
但不要混淆,您正在處理的示例只是從 STDIN 獲取輸入,用空格分隔每個參數,然後打印它,後跟:
.當給出多個-
' 時,您是在告訴paste
您接受參數,一次 2 個,一次 3 個,等等。
一次 2 個參數,用:
' 分隔:
$ seq 10 | paste -d ':' - -
1:2
3:4
5:6
7:8
9:10
$ seq 10 | paste -d ':' - - -
1:2:3
4:5:6
7:8:9
10::
順便說一句,如果您包含-s
開關,您將告訴您paste
按順序(串行)獲取參數。觀察當您在上面的範例之一中使用它時會發生什麼。
一次 2 個:
$ seq 10 | paste -sd ':' - -
1:2:3:4:5:6:7:8:9:10
一次 3 個:
$ seq 10 | paste -sd ':' - - -
1:2:3:4:5:6:7:8:9:10
答案2
$(command)
執行命令並替換其輸出。
{ list; }
是一個群組命令,在目前shell環境中執行多個命令。它與 類似(list)
,但它不會建立子 shell。
\command
用於忽略命令的別名,這可能會大大改變命令的預期行為。
行尾\
僅表示該行繼續,因此 shell 會將下一行視為目前行的一部分。當從上下文(左括號或引號)中顯而易見時,通常沒有必要。
答案3
APPCLASSPATH=$CLASSPATH:$({ \ \ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \ \ls -1 "$VOLTDB_LIB"/*.jar; \ \ls -1 "$VOLTDB_LIB"/extension/*.jar; \ } 2> /dev/null | paste -sd ':' - )
\ls
與 類似ls
,只不過 ifls
是別名,反斜線可防止別名擴充。這保證了ls
使用該命令,而不是使用可能添加不需要的輸出的別名,例如分類器後綴 ( -F
)。
這些ls
命令以現有檔案名稱作為參數調用,列出其參數,每行一個。此選項-1
無效,因為 的輸出ls
將發送到管道而不是終端。如果ls
接收到的參數不是現有文件的名稱,它將在其標準輸出上不顯示任何內容,而是顯示錯誤。命令中的錯誤ls
將被重定向到任何地方2> /dev/null
。有兩個原因ls
可能會收到不是檔案的參數:如果其中一個變數沒有引用現有的可讀目錄,或沒有與通配符模式相符的檔案。無論哪種情況,模式都會以未擴展的方式傳遞到ls
.
行末端的反斜線導致 shell 忽略後面的換行符號。它們在這裡都沒有用,因為在使用它們的每個點上,shell 都需要一個可選的換行符號。
大括號 { … } 將指令分組。複合命令{ \ls …; \ls …; \ls … ; }
透過管道傳輸到paste
並將其錯誤重定向到/dev/null
.
該paste
命令將所有輸入行連接在一起:
。它相當於,tr '\n' :
只是它沒有:
在末尾添加 a。
指令替換$(…)
導致 的輸出paste
被插值到變APPCLASSPATH
數值之後,CLASSPATH
並用冒號分隔兩個部分。
這是一個簡化版本。這與原始版本略有不同,因為如果沒有通配符模式匹配任何內容,APPCLASSPATH
則將等於CLASSPATH
沒有額外的尾隨冒號(這可能是可取的)。
APPCLASSPATH=$CLASSPATH:$(
\ls "$VOLTDB_VOLTDB"/voltdb-*.jar "$VOLTDB_LIB"/*.jar "$VOLTDB_LIB"/extension/*.jar |
tr '\n' :) 2>/dev/null
APPCLASSPATH=${APPCLASSPATH%:}