Bash

在 Bash 中,何時使用別名、何時編寫腳本以及何時編寫函式?

  • September 28, 2020

我用了將近 10 年的 Linux 使用來問這個問題。這都是反複試驗和隨機的深夜上網。

但人們不應該為此需要 10 年。如果我剛開始使用 Linux,我想知道:何時使用別名、何時編寫腳本以及何時編寫函式?

就別名而言,我將別名用於不帶參數的非常簡單的操作。

alias houston='cd /home/username/.scripts/'

這似乎很明顯。但是有些人會這樣做:

alias command="bash bashscriptname"

(並將其添加到.bashrc文件中)

有充分的理由這樣做嗎?我真的很努力,但我真的想不出在任何情況下我想這樣做。因此,如果存在會產生影響的極端情況,請在下面回答。

因為那是我在我的 PATH 和chmod +x它中放一些東西的地方,這是經過多年 Linux 反複試驗後出現的另一件事。

這讓我想到了下一個話題。例如,我.scripts/在主目錄中添加了一個隱藏文件夾 (),只需在我的.bashrc( PATH=$PATH:/home/username/.scripts/) 中添加一行,因此其中的任何執行檔都會自動自動完成。

如果我需要。

不過,我真的不需要那個,不是嗎?我只會將它用於不是 shell 的語言,比如 Python。

如果是外殼,我可以在裡面寫一個函式.bashrc

funcname () {
 somecommand -someARGS "$@"
}

正如我所說,我通過反複試驗發現了很多這種情況。而我只有在我的電腦當機時才真正看到了功能的美妙,而我不得不在他們不使用的時候使用我周圍的人的電腦。

我沒有將整個腳本目錄從一台電腦移動到另一台電腦,而是將其他所有人的 .bashrc 替換為我自己的,因為他們甚至從未進行過一次修改。

但我錯過了什麼嗎?

那麼,關於何時使用別名、何時編寫腳本以及何時編寫函式,您會告訴 Linux 初學者什麼?

如果不是很明顯,我假設回答這個問題的人會使用所有三個選項。如果你只使用別名,或者只使用腳本,或者只使用函式——或者如果你只使用別名和腳本或者別名和函式或者腳本和函式——這個問題並不是針對你的。

別名不應該(通常)有效地改變命令的預設選項。它只不過是命令名稱上的簡單文本替換。它不能對參數做任何事情,而是將它們傳遞給它實際執行的命令。因此,如果您只需要在單個命令的前面添加一個參數,則別名將起作用。常見的例子是

# Make ls output in color by default.
alias ls="ls --color=auto"
# make mv ask before overwriting a file by default
alias mv="mv -i"

當您需要做一些比別名更複雜的事情時,應該使用一個函式,但它本身不會有用。例如,在我詢問的關於根據它是否在管道中更改預設行為的問題上採用此答案:grep

grep() { 
   if [[ -t 1 ]]; then 
       command grep -n "$@"
   else 
       command grep "$@"
   fi
}

這是一個完美的函式範例,因為它對於別名來說太複雜了(根據條件需要不同的預設值),但在非互動式腳本中不需要它。

如果你得到太多的函式或太大的函式,請將它們放入隱藏目錄中的單獨文件中,並在你的~/.bashrc:

if [ -d ~/.bash_functions ]; then
   for file in ~/.bash_functions/*; do
       . "$file"
   done
fi

腳本應該獨立存在。它應該具有可重複使用或用於多個目的的價值。

其他答案提供了一些基於個人品味的軟通用準則,但忽略了在決定腳本、函式或別名時應考慮的許多相關事實。

別名和函式 ¹

  • 別名和函式的全部內容都儲存在 shell 的記憶體中。
  • 這樣做的一個自然結果是別名和函式只能由目前 shell 使用,而不能由您可以從 shell 呼叫的任何其他程序(如文本編輯器、腳本甚至同一 shell 的子實例)使用。
  • 別名和函式由目前shell 執行,即它們在shell 的目前環境中執行並影響shell 的目前環境。² 執行別名或函式不需要單獨的程序。

腳本

  • Shell 不會將腳本保存在記憶體中。相反,每次需要腳本時,都會從儲存它們的文件中讀取腳本。如果通過$PATH搜尋找到腳本,許多 shell 會將其路徑名的雜湊值儲存在記憶體中以節省將來$PATH查找的時間,但這是不使用時腳本記憶體佔用的程度。
  • 腳本可以通過比函式和別名更多的方式呼叫。它們可以作為參數傳遞給解釋器,如sh script,或直接作為執行檔呼叫,在這種情況下,#!/bin/sh呼叫 shebang 行(例如 )中的解釋器來執行它。在這兩種情況下,腳本都是由一個單獨的解釋器程序執行的,它自己的環境與你的 shell 不同,腳本不能以任何方式影響 shell 的環境。事實上,解釋器外殼甚至不必匹配呼叫外殼。因為以這種方式呼叫的腳本看起來像任何普通的執行檔,它們可以被任何程序使用。

最後,目前的 shell 可以讀取和執行腳本.,或者在某些 shell 中,source。在這種情況下,腳本的行為很像按需讀取的函式,而不是一直保存在記憶體中。

應用

鑑於上述情況,我們可以提出一些關於是否將某物製作為腳本或函式/別名的一般準則。

  • 除了你的 shell 之外的其他程序是否需要能夠使用它? 如果是這樣,它必須是一個腳本。
  • 您只希望它可以從互動式外殼中獲得嗎? 通常希望在互動執行時更改許多命令的預設行為而不影響外部命令/腳本。對於這種情況,使用在 shell 的“interactive-mode-only”rc 文件中設置的別名 / 函式(對於bashthis is .bashrc)。
  • 是否需要改變shell的環境? 函式/別名或源腳本都是可能的選擇。
  • 它是你經常使用的東西嗎? 將其保存在記憶體中可能更有效,因此如果可能,請將其設為函式/別名。
  • 相反,它是你很少使用的東西嗎? 在那種情況下,當你不需要它時,讓它佔用記憶體是沒有意義的,所以讓它成為一個腳本。

¹ 雖然函式和別名有一些重要的區別,但它們被歸為一組,因為函式可以做任何別名可以做的事情。別名不能有局部變數,也不能處理參數,而且它們對於超過一行的任何內容都很不方便。

² Unix 系統中的每個正在執行的程序都有一個由成對組成的環境variable=value,這些對通常包含全域配置設置,例如LANG預設語言環境和PATH指定可執行搜尋路徑。

引用自:https://unix.stackexchange.com/questions/30925