在執行指令後,有時我們會想要以特定的方式排序指令所輸出的結果,這時可以使用 sort 來做排序,本文記錄如何使用 sort 將特定字元作為分隔符,並對分隔後的特定欄位做排序。
情境
假設現在使用了 find 找出一些檔案,並用 sort 排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| % find $DOTFILES_ROOT/*/scripts -name install.sh | sort /Users/PeterChen/.dotfiles/bat/scripts/install.sh /Users/PeterChen/.dotfiles/cheat.sh/scripts/install.sh /Users/PeterChen/.dotfiles/exa/scripts/install.sh /Users/PeterChen/.dotfiles/fd/scripts/install.sh /Users/PeterChen/.dotfiles/fzf/scripts/install.sh /Users/PeterChen/.dotfiles/gcc/scripts/install.sh /Users/PeterChen/.dotfiles/git/scripts/install.sh /Users/PeterChen/.dotfiles/neofetch/scripts/install.sh /Users/PeterChen/.dotfiles/node.nvm/scripts/install.sh /Users/PeterChen/.dotfiles/nvim.packer.nvim/scripts/install.sh /Users/PeterChen/.dotfiles/nvim/scripts/install.sh /Users/PeterChen/.dotfiles/pip/scripts/install.sh /Users/PeterChen/.dotfiles/pyenv/scripts/install.sh /Users/PeterChen/.dotfiles/ripgrep/scripts/install.sh /Users/PeterChen/.dotfiles/rust.cargo/scripts/install.sh /Users/PeterChen/.dotfiles/rust/scripts/install.sh /Users/PeterChen/.dotfiles/sdkman/scripts/install.sh /Users/PeterChen/.dotfiles/tmux/scripts/install.sh /Users/PeterChen/.dotfiles/vim/scripts/install.sh /Users/PeterChen/.dotfiles/zsh.fzf-tab/scripts/install.sh /Users/PeterChen/.dotfiles/zsh.zplug/scripts/install.sh /Users/PeterChen/.dotfiles/zsh/scripts/install.sh
|
我們想要對 .dotfiles 的下層資料夾做排序,可以看到因為沒有設定分隔符的關係, sort 將整個字串視為排序的對象,因此會將路徑層的 / 也作為排序的依據,所以像是 nvim.packer.nvim 與 nvim 和 rust.cargo 與 rust 會是排序相反的狀況。
設定分隔符與排序欄位
sort 可以使用 -t 或是 --field-separator 來指定分隔符,並且使用 -k 或是 --key 指定要排序的欄位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| % find $DOTFILES_ROOT/*/scripts -name install.sh | sort -t '/' -k 5,5 /Users/PeterChen/.dotfiles/bat/scripts/install.sh /Users/PeterChen/.dotfiles/cheat.sh/scripts/install.sh /Users/PeterChen/.dotfiles/exa/scripts/install.sh /Users/PeterChen/.dotfiles/fd/scripts/install.sh /Users/PeterChen/.dotfiles/fzf/scripts/install.sh /Users/PeterChen/.dotfiles/gcc/scripts/install.sh /Users/PeterChen/.dotfiles/git/scripts/install.sh /Users/PeterChen/.dotfiles/neofetch/scripts/install.sh /Users/PeterChen/.dotfiles/node.nvm/scripts/install.sh /Users/PeterChen/.dotfiles/nvim/scripts/install.sh /Users/PeterChen/.dotfiles/nvim.packer.nvim/scripts/install.sh /Users/PeterChen/.dotfiles/pip/scripts/install.sh /Users/PeterChen/.dotfiles/pyenv/scripts/install.sh /Users/PeterChen/.dotfiles/ripgrep/scripts/install.sh /Users/PeterChen/.dotfiles/rust/scripts/install.sh /Users/PeterChen/.dotfiles/rust.cargo/scripts/install.sh /Users/PeterChen/.dotfiles/sdkman/scripts/install.sh /Users/PeterChen/.dotfiles/tmux/scripts/install.sh /Users/PeterChen/.dotfiles/vim/scripts/install.sh /Users/PeterChen/.dotfiles/zsh/scripts/install.sh /Users/PeterChen/.dotfiles/zsh.fzf-tab/scripts/install.sh /Users/PeterChen/.dotfiles/zsh.zplug/scripts/install.sh
|
-k 設置的是分隔後欄位的編號,第一個數字為起始欄位的編號,第二個是結束欄位的編號,中間以逗號 , 區隔。
我們的目標是排序 .dotfiles 的下層,因此是第五層(由於一開始就是 / ,因此第一個欄位的空字串也要列入計算),而由於我們只想對此層資料夾進行排序,因此起始與結束都設定 5 即可。
最後可以看到指令執行的結果完美地以 .dotfiles 下層資料夾由小到大排序好了。
總結
sort 會將整個字串作為搜尋結果,因此碰到像是目錄的斜線 / 時,也會將其包含在排序的目標中,這會使得排序的結果不如預期。
為了解決這個問題,我們可以使用 -t 參數設定分隔符,並使用 -k 選定要排序的依據欄位,藉此排除此問題。
參考資料