曆史上,shell一直是類Unix系統的本地指令行解釋器。它已被證明是Unix的主要功能之一,并發展成為一個全新的主題。Linux提供了各種功能強大的shell,包括Bash、Zsh、Tcsh和Ksh。這些外殼最令人驚訝的特性之一是其可程式設計性。建立簡單而有效的Linux shell腳本來處理日常工作非常容易。
1. Hello World
程式員經常通過學習hello world程式來學習新語言。這是一個簡單的程式,将字元串“HelloWorld”列印到标準輸出中。然後,使用vim或nano等編輯器建立hello-world.sh檔案,并将以下行複制到其中。
#!/bin/bash
echo "Hello World"
儲存并退出檔案。接下來,您需要使用以下指令使該檔案可執行。
$ chmod a+x hello-world.sh
可以使用以下兩個指令中的任何一個來運作此指令。
$ bash hello-world.sh
$ ./hello-world.sh
它将列印出傳遞給腳本内部回顯的字元串。
2.使用echo列印
echo指令用于在bash中列印資訊。它類似于C函數“printf”,并提供了許多常見選項,包括轉義序列和重定向。将以下行複制到名為echo.sh的檔案中,并使其可執行,如上所述。
#!/bin/bash
echo "Printing text"
echo -n "Printing text without newline"
echo -e "\nRemoving \t special \t characters\n"
運作腳本以檢視其功能。-e選項用于告訴echo傳遞給它的字元串包含特殊字元,需要擴充功能。
3.使用注釋
注釋對文檔很有用,是高品質代碼庫的要求。将注釋放在處理關鍵邏輯的代碼中是一種常見的做法。要注釋掉一行,隻需在其前面使用#(hash)字元。例如,請檢視下面的bash腳本示例。
#!/bin/bash
# Adding two values
((sum=25+35))
#Print the result
echo $sum
此腳本将輸出數字60。首先,在某些行之前使用#檢查注釋的使用方式。不過,第一行是一個例外。它被稱為shebang,讓系統知道在運作這個腳本時要使用哪個解釋器。
4.多行注釋
許多人使用多行注釋來記錄他們的shell腳本。在下一個名為comment.sh的腳本中檢查這是如何完成的。
#!/bin/bash
: '
This script calculates
the square of 5.
'
((area=5*5))
echo $area
注意多行注釋是如何放置在内部的:“和”字元。
5.While循環
while循環構造用于多次運作某些指令。檢視以下名為while.sh的腳本,以更好地了解此概念。
#!/bin/bash
i=0
while [ $i -le 2 ]
do
echo Number: $i
((i++))
done
是以,while循環采用以下形式。
while [ condition ]
do
commands 1
commands n
done
方括号周圍的空格是必填的。
6.For循環
for循環是另一種廣泛使用的bashshell構造,它允許使用者高效地疊代代碼。下面示範了一個簡單的示例。
#!/bin/bash
for (( counter=1; counter<=10; counter++ ))
do
echo -n "$counter "
done
printf "\n"
7.接收使用者輸入
#!/bin/bash
echo -n "Enter Something:"
read something
echo "You Entered: $something"
8.If語句
if CONDITION
then
STATEMENTS
fi
隻有當條件為真時,才會執行這些語句。fi關鍵字用于标記if語句的結尾。下面顯示了一個快速示例。
#!/bin/bash
echo -n "Enter a number: "
read num
if [[ $num -gt 10 ]]
then
echo "Number is greater than 10."
fi
如果通過輸入提供的數字大于10,上述程式将僅顯示輸出。-gt表示大于;類似地-lt表示小于-le表示小于等于;且-ge表示大于等于。此外,還需要[[]]。
9.使用If Else進行更多控制
将else構造與if結合起來,可以更好地控制腳本的邏輯。下面顯示了一個簡單的示例。
#!/bin/bash
read n
if [ $n -lt 10 ];
then
echo "It is a one digit number"
else
echo "It is a two digit number"
fi
其他部分需要放在if的動作部分之後和fi之前。
10.使用AND運算符
AND運算符允許我們的程式檢查是否同時滿足多個條件。由AND運算符分隔的所有部分必須為true。否則,包含AND的語句将傳回false。檢視下面的bash腳本示例,以更好地了解AND的工作原理。
#!/bin/bash
echo -n "Enter Number:"
read num
if [[ ( $num -lt 10 ) && ( $num%2 -eq 0 ) ]]; then
echo "Even Number"
else
echo "Odd Number"
fi
AND運算符由&&符号表示。
11.使用OR運算符
OR運算符是另一個關鍵的構造,它允許我們在腳本中實作複雜、健壯的程式設計邏輯。與AND相反,當OR運算符的任一操作數為真時,由OR運算符組成的語句傳回真。僅當由OR分隔的每個操作數為假時,它才傳回假。
#!/bin/bash
echo -n "Enter any number:"
read n
if [[ ( $n -eq 15 || $n -eq 45 ) ]]
then
echo "You won"
else
echo "You lost!"
fi
這個簡單的示例示範了OR運算符如何在Linuxshell腳本中工作。隻有當使用者輸入數字15或45時,它才會宣布使用者為獲勝者。||符号表示OR運算符。
12.使用El if
elif語句代表else if,并為實作鍊邏輯提供了一種友善的方法。通過評估以下示例,了解elif的工作原理。
#!/bin/bash
echo -n "Enter a number: "
read num
if [[ $num -gt 10 ]]
then
echo "Number is greater than 10."
elif [[ $num -eq 10 ]]
then
echo "Number is equal to 10."
else
echo "Number is less than 10."
fi
上面的程式是不言自明的,是以我們不會逐行剖析它。相反,更改腳本中的變量名稱和值等部分,以檢查它們如何一起工作。
13.case 條件
switch構造是Linux bash腳本提供的另一個強大功能。它可以用于需要嵌套條件的地方,但不希望使用複雜的if-else elif鍊。看看下一個例子。
#!/bin/bash
echo -n "Enter a number: "
read num
case $num in
100)
echo "Hundred!!" ;;
200)
echo "Double Hundred!!" ;;
*)
echo "Neither 100 nor 200" ;;
esac
條件寫在case和esac關鍵字之間。*)用于比對除100和200以外的所有輸入。
14.指令行參數
在許多情況下,直接從指令shell擷取參數是有益的。下面的示例示範了如何在bash中執行此操作。
#!/bin/bash
echo "Total arguments : $#"
echo "First Argument = $1"
echo "Second Argument = $2"
運作此腳本時,在其名稱後添加兩個附加參數。我将其命名為test.sh,調用過程概述如下。
$ ./test.sh Hey Howdy
是以,$1用于通路第一個參數,$2用于通路第二個參數,依此類推。最後,$#用于擷取參數總數。
15.使用名稱擷取參數
下面的示例顯示了如何擷取帶有名稱的指令行參數。
#!/bin/bash
for arg in "$@"
do
index=$(echo $arg | cut -f1 -d=)
val=$(echo $arg | cut -f2 -d=)
case $index in
X) x=$val;;
Y) y=$val;;
*)
esac
done
((result=x+y))
echo "X+Y=$result"
将此腳本命名為test.sh,并按如下所示調用它。
$ ./test.sh X=44 Y=100
它應該傳回X+Y=144。這裡的參數存儲在“$@”中,腳本使用Linuxcut指令擷取它們。
16.連接配接字元串
字元串處理對于廣泛的現代bash腳本來說非常重要。值得慶幸的是,它在bash中更加舒适,并允許以更精确、簡潔的方式實作這一點。請參見下面的示例,了解bash字元串連接配接。
#!/bin/bash
string1="Ubuntu"
string2="Pit"
string=$string1$string2
echo "$string is a great resource for Linux beginners."
17.字元串截取
與許多程式設計語言不同,bash不提供任何用于剪切字元串部分的内置函數。然而,下面的示例示範了如何使用參數展開來實作這一點。
#!/bin/bash
Str="Learn Bash Commands from UbuntuPit"
subStr=${Str:0:20}
echo $subStr
該腳本應列印出“學習Bash指令”作為其輸出。參數展開形式為${VAR_NAME:S:L}。這裡,S表示起始位置,L表示長度。
18.使用cut 做截取
可以在腳本中使用Linux cut指令來截取字元串的一部分,也就是子字元串。下一個示例顯示了如何做到這一點。
#!/bin/bash
Str="Learn Bash Commands from UbuntuPit"
#subStr=${Str:0:20}
subStr=$(echo $Str| cut -d ' ' -f 1-3)
echo $subStr
19.添加兩個值
在Linux shell腳本中執行算術運算非常容易。下面的示例示範了如何從使用者接收兩個數字作為輸入并将它們相加。
#!/bin/bash
echo -n "Enter first number:"
read x
echo -n "Enter second number:"
read y
(( sum=x+y ))
echo "The result of addition=$sum"
如您所見,在bash中添加數字相當簡單。
20.添加多個值
您可以使用循環擷取多個使用者輸入并将其添加到腳本中。以下示例顯示了這一點。
#!/bin/bash
sum=0
for (( counter=1; counter<5; counter++ ))
do
echo -n "Enter Your Number:"
read n
(( sum+=n ))
#echo -n "$counter "
done
printf "\n"
echo "Result is: $sum"
但是,省略(())将導緻字元串串聯而不是相加。是以,在你的程式中檢查類似的情況。
21.Bash中的函數
與任何程式設計方言一樣,函數在Linux shell腳本中扮演着重要角色。它們允許管理者建立自定義代碼塊以供頻繁使用。下面的示範将概述函數如何在Linux bash腳本中工作。
#!/bin/bash
function Add()
{
echo -n "Enter a Number: "
read x
echo -n "Enter another Number: "
read y
echo "Adiition is: $(( x+y ))"
}
Add
這裡我們像以前一樣添加了兩個數字。但在這裡,我們使用了一個名為Add的函數來完成這項工作。是以,每當您需要再次添加時,隻需調用此函數,而不必再次編寫該部分。
22.具有傳回值的函數
最神奇的功能之一是允許資料從一個函數傳遞到另一個函數。它在各種場景中都很有用。檢視下一個示例。
#!/bin/bash
function Greet() {
str="Hello $name, what brings you to UbuntuPit.com?"
echo $str
}
echo "-> what's your name?"
read name
val=$(Greet)
echo -e "-> $val"
這裡,輸出包含從Greet()函數接收的資料。
23.從Bash腳本建立目錄
使用shell腳本運作系統指令的能力使開發人員的工作效率大大提高。下面的簡單示例将向您展示如何在shell腳本中建立目錄。
#!/bin/bash
echo -n "Enter directory name ->"
read newdir
cmd="mkdir $newdir"
eval $cmd
該腳本隻需調用标準shell指令mkdir,并在仔細檢視時将目錄名傳遞給它。這個程式應該在檔案系統中建立一個目錄。您還可以傳遞指令以在backticks(“)内部執行,如下所示。
`mkdir $newdir`
24.确認存在後建立目錄
如果目前工作目錄中已包含同名檔案夾,則上述程式将無法運作。例如,下面的程式将檢查是否存在名為$dir的檔案夾,如果找不到,則隻建立一個。
#!/bin/bash
echo -n "Enter directory name ->"
read dir
if [ -d "$dir" ]
then
echo "Directory exists"
else
`mkdir $dir`
echo "Directory created"
fi
使用eval編寫此程式以提高bash腳本編寫技能。
25.讀取檔案
Bash腳本允許使用者非常有效地讀取檔案。下面的示例将展示如何使用shell腳本讀取檔案。首先,建立一個名為editors.txt的檔案,其中包含以下内容。
1. Vim
2. Emacs
3. ed
4. nano
5. Code
此腳本将輸出上述5行中的每一行。
#!/bin/bash
file='editors.txt'
while read line; do
echo $line
done < $file
26.删除檔案
以下程式将示範如何在Linux shell腳本中删除檔案。程式将首先要求使用者提供檔案名作為輸入,如果檔案名存在,則将其删除。Linux rm指令在此處執行删除操作。
#!/bin/bash
echo -n "Enter filename ->"
read name
rm -i $name
讓我們輸入editors.txt作為檔案名,并在要求确認時按y。它應該删除該檔案。
27.附加到檔案
下面的shell腳本示例将向您展示如何使用bash腳本将資料附加到檔案系統上的檔案。它向早期的editors.txt檔案添加了一行。
#!/bin/bash
echo "Before appending the file"
cat editors.txt
echo "6. NotePad++" >> editors.txt
echo "After appending the file"
cat editors.txt
現在您應該注意到,我們直接從Linux bash腳本使用日常終端指令。
28.測試檔案存在
下一個shell腳本示例顯示如何檢查bash程式中檔案的存在。
#!/bin/bash
filename=$1
if [ -f "$filename" ]; then
echo "File exists"
else
echo "File does not exist"
fi
我們直接從指令行傳遞檔案名作為參數。
29.從Shell腳本發送郵件
從bash腳本發送電子郵件非常簡單。下面的簡單示例将示範一種從bash應用程式執行此操作的方法。
#!/bin/bash
recipient=”[email protected]”
subject=”Greetings”
message=”Welcome to UbuntuPit”
`mail -s $subject $recipient <<< $message`
它将向收件人發送包含給定主題和消息的電子郵件。
30.解析日期和時間
下一個bash腳本示例将向您展示如何使用腳本處理日期和時間。同樣,Linuxdate指令用于擷取必要的資訊,我們的程式執行解析。
#!/bin/bash
year=`date +%Y`
month=`date +%m`
day=`date +%d`
hour=`date +%H`
minute=`date +%M`
second=`date +%S`
echo `date`
echo "Current Date is: $day-$month-$year"
echo "Current Time is: $hour:$minute:$second"
運作此程式以了解其工作原理。此外,嘗試從終端運作date指令。
31.sleep指令
sleep指令允許shell腳本在指令之間暫停。它在許多場景中都很有用,例如執行系統級作業。下一個示例顯示了shell腳本中的sleep指令。
#!/bin/bash
echo "How long to wait?"
read time
sleep $time
echo "Waited for $time seconds!"
該程式暫停最後一條指令的執行,直到$time秒,在本例中,使用者提供了這一點。
32.wait指令
wait指令用于暫停Linux bash腳本中的系統程序。檢視下面的示例,詳細了解這在bash中的工作方式。
#!/bin/bash
echo "Testing wait command"
sleep 5 &
pid=$!
kill $pid
wait $pid
echo $pid was terminated.
33.顯示上次更新的檔案
有時,您可能需要為某些操作查找最後更新的檔案。下面的簡單程式向我們展示了如何在bash中使用awk指令執行此操作。它将列出目前工作目錄中最近更新或建立的檔案。
#!/bin/bash
ls -lrt | grep ^- | awk 'END{print $NF}'
為了簡單起見,我們将避免在本示例中描述awk的功能。相反,您可以簡單地複制此代碼來完成任務。
34.添加批處理擴充
下面的示例将對目錄中的所有檔案應用自定義擴充名。建立一個新目錄,并将一些檔案放在其中以供示範。我的檔案夾共有五個檔案,每個檔案名為test,後跟(0-4)。我已将此腳本程式設計為在檔案末尾添加(.UP)。您可以添加所需的任何擴充名。
#!/bin/bash
dir=$1
for file in `ls $1/*`
do
mv $file $file.UP
done
首先,不要從任何正常目錄嘗試此腳本;相反,請從測試目錄運作此指令。此外,您需要提供檔案的目錄名作為指令行參數。對目前工作目錄使用句點(.)。
35.列印檔案或目錄的數量
下面的Linuxbash腳本查找給定目錄中存在的檔案或檔案夾的數量。它使用Linux find指令來執行此操作。首先,需要傳遞目錄名以從指令行搜尋檔案。
#!/bin/bash
if [ -d "$@" ]; then
echo "Files found: $(find "$@" -type f | wc -l)"
echo "Folders found: $(find "$@" -type d | wc -l)"
else
echo "[ERROR] Please retry with another folder."
exit 1
fi
如果指定的目錄不可用或存在權限問題,程式将要求使用者重試。
36.清理日志檔案
下一個簡單的示例示範了在現實生活中使用shell腳本的簡便方法。該程式隻需删除/var/log目錄中的所有日志檔案。您可以更改儲存此目錄的變量以清理其他日志。
#!/bin/bash
LOG_DIR=/var/log
cd $LOG_DIR
cat /dev/null > messages
cat /dev/null > wtmp
echo "Logs cleaned up."
請記住以root身份運作此Linuxshell腳本。
37.使用Bash備份腳本
Shell腳本提供了一種強大的方法來備份檔案和目錄。以下示例将備份過去24小時内修改的每個檔案或目錄。該程式使用find指令執行此操作。
#!/bin/bash
BACKUPFILE=backup-$(date +%m-%d-%Y)
archive=${1:-$BACKUPFILE}
find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar"
echo "Directory $PWD backed up in archive file \"$archive.tar.gz\"."
exit 0
備份過程成功後,它将列印檔案和目錄的名稱。
38.檢查你是否是root使用者
下面的示例示範了通過Linux bash腳本快速确定使用者是否為root使用者的方法。
#!/bin/bash
ROOT_UID=0
if [ "$UID" -eq "$ROOT_UID" ]
then
echo "You are root."
else
echo "You are not root"
fi
exit 0
此腳本的輸出取決于運作它的使用者。它将根據$UID比對根使用者。
39.從檔案中删除重複行
檔案處理需要相當長的時間,并在許多方面阻礙了管理者的工作效率。例如,在檔案中搜尋重複項可能會成為一項艱巨的任務。幸運的是,您可以使用一個簡短的shell腳本來完成此操作。
#! /bin/sh
echo -n "Enter Filename-> "
read filename
if [ -f "$filename" ]; then
sort $filename | uniq | tee sorted.txt
else
echo "No $filename in $pwd...try again"
fi
exit 0
上面的腳本逐行周遊檔案并删除所有重複的行。然後,它将新内容放入新檔案,并保持原始檔案的完整性。
40.系統維護
我經常使用一個小的Linuxshell腳本來更新我的系統,而不是手動更新。下面的簡單shell腳本将向您展示如何做到這一點。
#!/bin/bash
echo -e "\n$(date "+%d-%m-%Y --- %T") --- Starting work\n"
apt-get update
apt-get -y upgrade
apt-get -y autoremove
apt-get autoclean
echo -e "\n$(date "+%T") \t Script Terminated"
該腳本還處理不再需要的舊包。您需要使用sudo運作此腳本,否則它将無法正常工作。