9 個 Bash 腳本示例讓您開始使用 Linux

已發表: 2022-07-05
筆記本電腦屏幕上的 Linux 終端。
fatmawati achmad zaenuri/Shutterstock.com

如果您剛開始在 Linux 上編寫 Bash 腳本,那麼紮實掌握基礎知識將對您有利。 它們是更深入的知識和更高的腳本技能的基礎。

記住,讓你的腳本可執行

要讓 shell 執行腳本,腳本必須具有可執行文件權限集。 沒有這個,你的腳本只是一個文本文件。 有了它,它仍然是一個文本文件,但 shell 知道它包含指令,並會在腳本啟動時嘗試執行它們。

編寫腳本的全部意義在於它們可以運行,所以第一步是要知道如何讓 Linux 知道你的腳本應該被認為是可執行的。

chmod命令讓我們設置文件權限。 可以使用 +x 標誌設置執行權限。

 chmod +x script1.sh 

使腳本可執行

您需要對每個腳本執行此操作。 將“script1.sh”替換為您的腳本名稱。

1. 奇怪的第一行是什麼?

腳本的第一行告訴 shell 應該調用哪個解釋器來運行該腳本。 第一行必須以 shebang 開頭,“#!”,也稱為 hashbang。 這 ”#!” 告訴 shell 這一行包含腳本所針對的解釋器的路徑和名稱。

這很重要,因為如果您編寫了要在 Bash 中運行的腳本,您不希望它被不同的 shell 解釋。 可能存在不兼容的情況。 與大多數 shell 一樣,Bash 有自己的語法和功能,而其他 shell 沒有,或者以不同的方式實現。

當您運行腳本時,當前 shell 打開腳本並確定應該使用哪個 shell 或解釋器來執行該腳本。 然後它啟動那個 shell 並將腳本傳遞給它。

 #!/bin/bash

echo 在 $SHELL 中運行

該腳本的第一行可以讀作“使用位於 /bin/bash 的解釋器來運行此腳本”。

腳本中唯一的一行將$SHELL環境變量中保存的值寫入終端屏幕。 這證實了使用 Bash 執行腳本。

 ./script1.sh 

識別腳本在其下運行的 shell

作為一個小技巧,我們可以證明腳本被傳遞給我們選擇的任何解釋器。

 #!/bin/cat
所有文本行都傳遞給 cat 命令
並打印在終端窗口中。 那包含著
舍邦線。
 腳本2.sh 

通過將腳本傳遞給 cat 命令來運行腳本

此腳本由當前 shell 啟動並傳遞給cat命令。 cat命令“運行”腳本。

像這樣編寫你的 shebangs 假設你知道 shell 或其他解釋器在目標機器上的位置。 99% 的情況下,這都很好。 但是有些人喜歡對沖他們的賭注並像這樣寫他們的shebangs:

 #!/usr/bin/env bash

echo 在 $SHELL 中運行
腳本3.sh 

運行搜索 shell 的腳本

當腳本啟動時,shell 會搜索命名 shell 的位置。 如果 shell 恰好位於非標準位置,這種方法可以避免“錯誤解釋器”錯誤。

別聽,他在說謊!

在 Linux 中,總是有不止一種方法可以給貓剝皮或證明作者的錯誤。 完全符合事實的是,有一種方法可以在沒有 shebang 的情況下運行腳本,並且不讓它們可執行。

如果您啟動要執行腳本的 shell 並將腳本作為命令行參數傳遞,則 shell 將啟動並運行腳本——無論它是否可執行。 因為您在命令行上選擇了 shell,所以不需要 shebang。

這是整個腳本:

 echo "我被處決了" $SHELL

我們將使用ls來查看該腳本確實不可執行,並使用該腳本的名稱啟動 Bash:

 ls
 bash script4.sh 

運行沒有可執行文件權限集且沒有 shebang 的腳本

還有一種方法可以讓當前shell 運行腳本,而不是專門為執行腳本而啟動的 shell。 如果使用source命令,可以縮寫為單個句點“ . “,您的腳本由您當前的 shell 執行。

因此,要在沒有 shebang、沒有可執行文件權限且不啟動另一個 shell 的情況下運行腳本,您可以使用以下任一命令:

 源腳本4.sh
 . 腳本4.sh 

在當前 shell 中運行腳本

儘管這是可能的,但不建議將其作為一般解決方案。 有缺點。

如果腳本不包含 shebang,則您無法判斷它是為哪個 shell 編寫的。 一年後你會記得嗎? 如果腳本沒有設置可執行權限, ls命令不會將其識別為可執行文件,也不會使用顏色將腳本與純文本文件區分開來。

相關:命令行:為什麼人們仍然為它們煩惱?

2. 打印文本

向終端寫入文本是一項常見要求。 一點視覺反饋會有很長的路要走。

對於簡單的消息, echo命令就足夠了。 它允許對文本進行一些格式化,也允許您使用變量。

 #!/bin/bash

echo 這是一個簡單的字符串。
echo "這是一個包含'單引號'的字符串,所以它用雙引號括起來。"
echo "這將打印用戶名:" $USER
echo -e "-e 選項讓我們使用\n格式化指令\n分割字符串。"
 ./script5.sh 

使用 echo 命令寫入終端窗口的腳本

printf命令為我們提供了更大的靈活性和更好的格式化功能,包括數字轉換。

此腳本使用三個不同的數字基數打印相同的數字。 十六進製版本也被格式化為以大寫形式打印,前導零和三位數的寬度。

 #!/bin/bash

printf "十進制:%d,八進制:%o,十六進制:%03X\n" 32 32 32
 ./script6.sh 

使用 printf 轉換和格式化數字的腳本

請注意,與echo不同,您必須告訴printf以“ \n ”標記開始新行。

3. 創建和使用變量

變量允許您在程序中存儲值並操作和使用它們。 您可以創建自己的變量或使用環境變量作為系統值。

 #!/bin/bash

millennium_text="千禧年以來的歲月:"

current_time=$(日期'+%H:%M:%S')
todays_date=$( 日期 '+%F' )
年=$(日期'+%Y')

echo "當前時間:" $current_time
echo "今天的日期:" $todays_date

years_since_Y2K=$(( 年 - 2000 ))

迴聲 $millennium_text $years_since_Y2K

此腳本創建一個名為millennium_text的字符串變量。 它包含一行文本。

然後它創建三個數值變量。

  • current_time變量被初始化為腳本執行的時間。
  • todays_date變量設置為腳本運行的日期。
  • year變量保存當前年份。

要訪問存儲在變量中的,請在其名稱前加上美元符號“$”。

 ./script7.sh 

使用變量計算時間段的腳本

該腳本打印時間和日期,然後計算自千禧年以來已經過去了多少年,並將其存儲在years_since_Y2K變量中。

最後,它打印包含在millennium_text變量中的字符串和存儲在years_since_Y2K中的數值。

相關:如何在 Bash 中使用變量

4. 處理用戶輸入

要允許用戶輸入腳本將使用的值,您需要能夠捕獲用戶的鍵盤輸入。 Bash read命令允許 ut 做到這一點。 這是一個簡單的例子。

 #!/bin/bash

echo "輸入一個數字並點擊\"Enter\""
讀取用戶編號 1;
echo "輸入另一個數字並點擊 \"Enter\""
讀取用戶編號2;

printf "你輸入了:%d 和 %d\n" $user_number1 $user_number2
printf "把它們加在一起:%d\n" $((user_number1 + user_number2))

該腳本提示輸入兩個數字。 它們從鍵盤讀取並存儲在兩個變量user_number1user_number2中。

該腳本將數字打印到終端窗口,將它們加在一起,然後打印總數。

 ./script8.sh 

使用 read 命令捕獲用戶輸入

我們可以使用-p (提示)選項將提示組合到read命令中。

 #!/bin/bash

read -p "輸入一個數字並點擊\"Enter\" " user_number1;
read -p "輸入另一個數字並點擊\"Enter\" " user_number2;

printf "你輸入了:%d 和 %d\n" $user_number1 $user_number2
printf "把它們加在一起:%d\n" $((user_number1 + user_number2))

這使事情更整潔,更容易閱讀。 易於閱讀的腳本也更易於調試。

 ./script9.sh 

使用 read 命令和 -p(提示)選項捕獲用戶輸入

該腳本現在的行為略有不同。 用戶輸入與提示位於同一行。

要捕獲鍵盤輸入而不將其回顯到終端窗口,請使用-s (靜默)選項。

 #!/bin/bash

read -s -p "輸入您的密碼並點擊 \"Enter\" " secret_PIN;

printf "\nShhh ... 它是 %d\n" $secret_PIN
 ./script10.sh 

捕獲用戶輸入而不將其寫入終端窗口

輸入值被捕獲並存儲在一個名為secret_PIN的變量中,但是當用戶鍵入它時它不會回顯到屏幕上。 之後你用它做什麼取決於你。

5.接受參數

有時接受用戶輸入作為命令行參數比讓腳本等待輸入更方便。 將值傳遞給腳本很容易。 它們可以在腳本中被引用,就像它們是任何其他變量一樣。

第一個參數變為變量$1 ,第二個參數變為變量$2 ,依此類推。 變量$0始終保存腳本的名稱,變量$#保存命令行中提供的參數數量。 變量$@是一個包含所有命令行參數的字符串。

 #!/bin/bash

printf "這個腳本被調用:%s\n" $0
printf "你使用了 %d 個命令行參數\n" $#

# 循環遍歷變量
對於“$@”中的參數; 做
  迴聲“$參數”
完畢

echo "參數 2 是:" $2

該腳本使用$0$#來打印一些信息。 然後使用?@循環所有命令行參數。 它使用$2來展示如何訪問單個特定的參數值。

 ./script11.sh 

在腳本中使用命令行參數

將幾個單詞用引號“””括起來,將它們組合成一個參數。

6. 從文件中讀取數據

知道如何從文件中讀取數據是一項很棒的技能。 我們可以在 Bash 中使用 while 循環來做到這一點。

 #!/bin/bash

行數=0

而 IFS='' 讀取 -r LinefromFile || [[ -n "${LinefromFile}" ]]; 做

  ((線數++))
  echo "讀取行 $LineCount: ${LinefromFile}"

完成 <"$1"

我們將希望腳本處理的文件的名稱作為命令行參數傳遞。 這將是唯一的參數,因此在腳本中$1將保存文件名。 我們將該文件重定向到while循環中。

如何在 Linux Bash 腳本中逐行處理文件
相關如何在 Linux Bash 腳本中逐行處理文件

while循環使用IFS=''賦值將內部字段分隔符設置為空字符串。 這可以防止read命令在空白處拆分行。 只有行尾的回車才被認為是真正的行尾。

[[ -n "${LinefromFile}" ]]子句滿足文件中最後一行不以回車符結尾的可能性。 即使沒有,最後一行也將被正確處理並被視為常規的 POSIX 兼容行。

 ./script12.sh 閃爍.txt 

使用腳本從文件中讀取文本

7. 使用條件測試

如果您希望腳本針對不同的條件執行不同的操作,則需要執行條件測試。 雙括號測試語法起初提供了大量的選項。

 #!/bin/bash

價格=$1

如果 [[ 價格 -ge 15 ]];
然後
  迴聲“太貴了。”
別的
  迴聲“買!”
菲

Bash 提供了一整套比較運算符,可讓您確定諸如文件是否存在、是否可以讀取文件、是否可以寫入文件以及目錄是否存在等內容。

它還對等於-qe 、大於-gt 、小於或等於-le等進行了數值測試,儘管您也可以使用熟悉的==>=<=表示法。

 ./script13.sh 13
 ./script13.sh 14
 ./script13.sh 15
 ./script13.sh 16 

運行帶有條件測試的腳本

8. for 循環的威力

一遍又一遍地重複動作最好使用循環來完成。 for循環允許您多次運行循環。 這可能達到一個特定的數字,或者可能直到循環通過項目列表。

 #!/bin/bash

對於 (( i=0; i<=$1; i++ ))
做
  echo "C 風格的 for 循環:" $i
完畢

對於我在 {1..4}
做
  echo "For 循環範圍:" $i
完畢

對於 i 在 "零" "一" "二" "三"
做
  echo "帶有單詞列表的 For 循環:" $i
完畢

網站="如何極客"

對於我在 $website
做
  echo "帶有單詞集合的 For 循環:" $i
完畢

所有這些循環都是for循環,但它們使用不同類型的循環語句和數據。

 ./script14.sh 3 

使用四種不同類型的 for 循環運行腳本

第一個循環是經典的 C 風格for循環。 循環計數器i初始化為零,並隨著循環的每個循環遞增。 當i的值小於或等於$1中保存的值時,循環將繼續運行。

第二個循環處理從 1 到 4 的數字範圍。第三個循環處理一個單詞列表。 雖然有更多的詞要處理,但循環會不斷重複。

最後一個循環遍歷字符串變量中的單詞列表。

9. 功能

函數允許您將代碼段封裝到命名例程中,這些例程可以從腳本中的任何位置調用。

假設我們希望從文件中讀取行的腳本對每一行進行某種處理。 將該代碼包含在函數中會很方便。

 #!/bin/bash

行數=0

函數 count_words() {
  printf "%d 行中的 %d 個單詞\n" $(echo $1 | wc -w) $2
}

而 IFS='' 讀取 -r LinefromFile || [[ -n "${LinefromFile}" ]]; 做

  ((線數++))
  count_words "$LinefromFile" $LineCount

完成 <"$1"

count_words "這不在循環中" 99

我們通過添加一個名為count_words的函數來修改我們的文件讀取程序。 它是在我們需要使用它之前定義的。

函數定義以單詞function開頭。 接下來是我們函數的唯一名稱,後跟括號“ () ”。 函數的主體包含在大括號“{}”中。

函數定義不會導致任何代碼被執行。 在調用函數之前,函數中的任何內容都不會運行。

count_words函數打印一行文本中的單詞數和行號。 這兩個參數被傳遞到​​函數中,就像參數被傳遞到​​腳本中一樣。 第一個參數成為函數變量$1 ,第二個參數成為函數變量$2 ,依此類推。

while循環從文件中讀取每一行並將其與行號一起傳遞給count_words函數。 為了表明我們可以從腳本中的不同位置調用該函數,我們在while循環之外再次調用它。

 ./script15.sh 閃爍.txt 

運行使用函數的腳本

不要害怕學習曲線

腳本是有益的和有用的,但很難進入。 一旦掌握了一些可重用的技術,您將能夠相對輕鬆地編寫有價值的腳本。 然後您可以查看更高級的功能。

在跑步之前先步行,並花時間享受旅程。

相關: 10 個適合初學者的基本 Linux 命令