You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
在下面執行 clang-format 時就會遇到 word splitting 的問題,整串會被解讀成:
++ which clang-format
+ CLANG_FORMAT=/bin/clang-format
+ OPTIONS='-style="{BasedOnStyle: LLVM, IndentWidth: 2}"'
+ /bin/clang-format '-style="{BasedOnStyle:' LLVM, IndentWidth: '2}"' test.c
No such file or directory
No such file or directory
No such file or directory
Invalid value for -style, using LLVM style
OPTIONS 被展開後,經過 word splitting 以 <space> 切開,導致參數變成了多個,這邊使用上面的 args 來觀察:
為了做各種實驗發現一個蠻不錯的選項可以設定:set -x 可以設定 shell 的選項,而 x 的功能是 "Print commands and their arguments as they are executed." 也就是經過 shell 解析後的最後結果會被印出來,像是有變數的話就會是以展開後的形式印出。
此外若是一個腳本的話可以用以下方法:
bash-4.2$ cat t.sh
#!/usr/bin/env bash
subject="word1 word2"
args="-s "$subject""
ls $args
ls "$args"
bash-4.2$ bash -x t.sh
+ subject='word1 word2'
+ args='-s word1 word2'
+ ls -s word1 word2
ls: cannot access word1: No such file or directory
ls: cannot access word2: No such file or directory
+ ls '-s word1 word2'
ls: invalid option -- ' '
Try 'ls --help' for more information.
[1]: The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion. (From the bash man page) ↵
前言
WordSplitting
多數的 shell 指令都會加上一些參數來去執行,而 word splitting 就是決定參數是哪些的過程中的一部分。
原文提供了一個腳本可以把 shell 建構好的參數一個個印出來。
使用情況大致如下:
Word splitting 的執行順位很後面 [1],在多數種類的展開(expansion)後面,而結果是根據一個特別的變數 IFS - Internal Field Separator 來決定要以什麼字元做切割,當沒有特別設定 IFS 時,預設是 <space>, <tab>, <newline>,舉例來說:
若是將 IFS 換成別的字元:
遇到的問題
在 Git Hook 腳本中,將
clang-format
的選項用變數存了起來:在下面執行
clang-format
時就會遇到 word splitting 的問題,整串會被解讀成:OPTIONS 被展開後,經過 word splitting 以 <space> 切開,導致參數變成了多個,這邊使用上面的
args
來觀察:原本預期只有兩個參數的指令,變成了四個參數,導致上面多了三個 "No such file or directory" 的錯誤,而第四個錯誤是
clang-format
去解析-style
時所發生的 [2]。解決方法
原始的解法是利用 array 把參數當成一個字詞包起來,並將其展開:
後來在撰寫這篇筆記才發現
clang-format
的說明-style="{key: value, ...}"
中的雙引號是為了讓 shell 判斷是一整個字詞(詳見此),不要將其切開,並非是自身 parser 的規定。如此一來,第二種解法是較為簡單且清楚的,只需要在展開變數時用雙引號來壓過 word splitting 的效果即可。Misc
為了做各種實驗發現一個蠻不錯的選項可以設定:
set -x
可以設定 shell 的選項,而x
的功能是 "Print commands and their arguments as they are executed." 也就是經過 shell 解析後的最後結果會被印出來,像是有變數的話就會是以展開後的形式印出。此外若是一個腳本的話可以用以下方法:
-style
的形式有三種,"{: , ...}", "<style name>", "file",判斷式可參考llvm::Expected<FormatStyle>::getStyle
↵Ref
The text was updated successfully, but these errors were encountered: