2015-02-09 33 views
2

以下是來自shell腳本的代碼片段。 (這是從MPFR庫的配置腳本開始的,它以#!/ bin/sh開頭,原始腳本長度超過17000行..用於構建gcc時使用。)關於由autoconf生成的shell腳本的部分問題的許多問題

因爲我在短片中有很多問題代碼,我在代碼中嵌入了我的問題。請有人向我解釋爲什麼代碼是這樣的?另外,雖然我有一個模糊的想法,但是如果有人能夠解釋這段代碼在做什麼(我知道這將是困難的,因爲它只是大腳本的一部分),我將不勝感激。

if { { ac_try="$ac_link"  
    # <---- question 1 : why is the first curly bracket used for if condition? (probably just for grouping and using the last return code) 
    # <---- question 2 : Is this second bracket for locally used code(probably)? 
case "(($ac_try" in   # <---- question 3 : what is this "((" symbol? 
    *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; 
    *) ac_try_echo=$ac_try;; 
esac 
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" 
$as_echo "$ac_try_echo"; } >&5  # <---- question 4 : what is this >&5 redirection? I know >&{1,2,3} but not 5. 
    (eval "$ac_link") 2>&5 
    # <----- question 5 : why use sub-shell here? not to use eval result? 
    ac_status=$? 
    $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 
    test $ac_status = 0; }; then : # <---- question 6 : is this ':'(nop) here ? 
    .... 
    some commands 
    .... 
else 
    .... 
    some commands 
    .... 
fi 
+5

'configure'腳本不能被讀取。它們是從其他來源生成的。至於你的問題:請刪除所有元評註,其中一個規則是:每個問題一個問題。 – Mat 2015-02-09 06:10:18

+0

墊,我明白。此配置腳本必須來自自動配置,因此變量以ac_ ..開頭。但爲了解決問題,有時我必須查看腳本,並且可以解決問題。所以請耐心等待幾天。只是爲了看到任何答案。它會幫助別人。 – 2015-02-09 06:13:44

+0

閱讀。雖然它不能解釋自動生成的autoconf的特性,這與幾十年來圍繞bug的shell實現有關。 [shell的Posix描述](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html) – rici 2015-02-09 06:14:20

回答

3

從Bash的手冊頁:

{列表; } 列表僅在當前shell環境中執行。列表 必須以換行符或分號結尾。這被稱爲 作爲一個組命令。返回狀態是 列表的退出狀態。請注意,與元字符(和)不同,{和}是保留字,必須在允許保留字 被識別的地方出現。由於它們不會導致分詞,所以它們 必須通過空白或其他shell 元字符與列表分開。

{}只是列出一些命令來運行,非常像cmd1; cmd2; cmd3。例如,如果你寫cmd1 ; cmd2 | cmd3,你的意思是{cmd1; cmd2;} | cmd3cmd1; {cmd2 | cmd3;}

{{ }}只是嵌套的命令列表,很簡單:例如: {cmd1; cmd2; {cmd3; cmd4;}; }

對於問題3,((只是在與以下模式匹配的源字符串中。如果您問爲什麼使用它,我們需要$ac_try的可能值來分析原因。老實說,我沒有看到許多shell腳本在源字符串前添加((以匹配模式。

對於問題4, >&5:如果文件描述符5尚未創建(在腳本的任何部分即提到... =>要小心,你需要關心的範圍,一些代碼運行在子shell ,它被視爲一個子外殼上下文/作用域),使用描述符5創建一個未命名的文件(如果你喜歡,就是臨時文件)。該文件可以在腳本的其他部分用作輸入。

例如,在我對另一個問題here的回答中查看提及「交換STDIN和STDOUT」的部分。

對於問題5,eval,我不太清楚,只是一個快速的猜測(和它取決於什麼命令它evals)通過提供你一個例子,爲什麼子shell使得一些差異:

cmd="Foo=1; ls" 
(eval $cmd) # this command runs in sub-shell and thus $Foo in current shell will not be changed. 
eval $cmd  # this command runs in current shell and thus $Foo is changed, and it will affect all subsequent commands. 

對於問題6,仔細查看我在答案頂部提到的手冊頁{}列表語法,需要最終的;。即{cmd1; cmd2 ; }最後的;是必需的。

--- UPDATE ---

問題6:抱歉沒有看到冒號...:-) 這不適用:請參閱this link

+0

謝謝。現在我明白**問題1,2 **(代碼塊,只需使用if的最終返回碼)。你應該是正確的**問題3 **「((」但它似乎有一個特殊的技巧使用「((」。(我看到很多這種情況下「(($」在配置文件中。 4 **,現在我看到文件描述符5的第一外觀是 'EXEC 5 >>的config.log { 布拉布拉 }>&5 ' 和**問題6 **,我詢問:(結腸)在'then'之後返回'true'。對於問題5或者6 **有更多的建議或者幫助嗎?(好像將條件重置爲真) – 2015-02-09 07:47:08

+0

@ChanKim:鑑於'exec 5 >> config.log ',那麼任何重定向到文件描述符5的內容都將寫入配置日誌文件,例如'(eval「$ ac_link」)2>&5'將錯誤從'eval'發送到配置日誌文件。 Q5和Q6,看到我對主要問題的評論。 – 2015-02-09 07:51:34

+0

@JonathanLeffler哦,我錯過了你的評論。謝謝!(所以我的猜測幾乎是正確的。) – 2015-02-09 07:55:35