對于背景關系,我正在嘗試創建一個過于簡化的 bash 版本,而不是像 bash 完整的腳本解釋器,只是一系列命令和運算子的(|,||, &&, <, >, <<, >>,$, $?)小型解釋器,我使用的心智模型簡而言之是:
- Lexer Expander:在第一階段,我使用一個簡單的狀態機來 lex 和存盤資料(命令、引數、重定向檔案等)和 lex 輸入到令牌中,我擴展 env 變數并處理詞法錯誤。(就像檢查有效字符的有限狀態)。
- 決議器:在第二個階段,我打算從令牌 資料中創建一個 AST,并處理決議錯誤。
- 執行者:最后我將執行 AST。
不,我處于決議器階段,我正在嘗試考慮如何處理決議錯誤,現在我的想法超出了有效陳述句的可能范圍,似乎很難檢查這樣的有效性輸入導致范圍太大或者至少我是這么認為的,而且我確信這個問題有一些通用的解決方案,為什么我確定?因為 bash 已經做到了。
例如這個陳述句:
$ < $FILE || && > outfile
從詞法分析器的角度來看,這一切都是明亮而閃亮的,但從決議器的角度來看,它肯定不是有效的輸入。現在一種可能的解決方案是檢查輸入中是否有命令令牌,如果不是則無效。但是這個呢:
$ || ls > $FILE && cat < $FILE
同樣,所有有效的詞位,但不可決議的陳述句,也許也可以檢查“如果該行以 OR 或 AND 標記錯誤開頭。”。
現在具體的問題是bash 如何準確決議這些命令和運算子的組合,要么有某種更通用的解決方案,要么我對我認為無效的輸入進行 if&else 錯誤檢查。老實說,這看起來既愚蠢又麻煩。
uj5u.com熱心網友回復:
shell 決議的大部分復雜性在于標記化,盡管您當然不需要擔心多年來悄悄出現的所有復雜性。語法本身很簡單。它被設計為由使用 Bison(或其他 yacc 衍生工具)等工具生成的決議器進行決議,而這正是 Bash 的作業原理。
Bash 識別的各種語法規則散布在整個Bash 手冊中,但是語法是基于 Posix 標準中指定的標準 shell 語法,這可能是一個更容易的起點。在該檔案中,包含的語法基本上是一個 Yacc 輸入檔案(沒有任何實際實作所需的語意操作);您可以在第 2.10 節的末尾找到它。不過,請務必閱讀該部分的開頭部分,因為它包含有關令牌如何分類的重要資訊。另外,請注意第 2.3 節,令牌識別。
在這兩部分之間,您會找到對 shell 參考規則的精確描述以及在決議之前完成的各種擴展(或者,更好地說,與決議混合,因為命令替換使整個程序遞回。)您可能不想吸收所有這些都是第一次閱讀,盡管它也將幫助您更有效地使用 shell。
Bash 實作了更多功能,但可能大部分或全部功能超出了您的需求。
uj5u.com熱心網友回復:
@choroba 有正確的想法- 要準確了解 Bash 如何決議腳本,您需要查看 Bash 的源代碼。對于 Bash 在越來越復雜的情況下如何作業,基本上有分形的經驗法則,任何足夠短以適應 SO 回應的描述可能都不夠詳細,無法為您提供全貌。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/478759.html
下一篇:使用sed更改特定行中的特定字符
