【shell】shell基礎

一、什麼是shell?

shell是處於用戶和Linux系統之間的命令解釋器。


二、shell基礎操作

1.創建shell腳本

vi first_shell.sh

2.shell腳本的格式

#!/bin/bash
#filename:first_shell
#created day:2019.9.28
echo "Hello World!"

第一行:#!/bin/bash

#!是一種約定標記,他告訴系統這個腳本需要用/bin/bash解釋器來執行,如果不寫這一行腳本也可以執行,只是系統會根據自身的shell解釋器來解釋腳本。

第二和第三行

shell腳本使用#來標識註釋。

第四行:echo “Hello World!”

shell將沒有#標識的語句解釋爲命令。

shell腳本的命令語句可以在行末使用;表示結束,也可以不適用,但是一行有多條語句必須使用;分隔。

3.執行腳本

/bin/bash first_shell.sh

輸出結果:

Hello World!

三、變量

1.局部變量

在這裏插入圖片描述

shell中沒有特別標註的變量都屬於局部變量,如:

#!/bin/bash
#by goulandis 2019.9.28
A="asd"
echo $A
A=123
echo $A

局部變量只能在腳本內部才能使用。

shell是非類型的解釋型語言,變量的類型在運行事確定。

字符串也可以不要使用"",如:A=asd,輸出結果也是一樣的,但是不使用""賦值時,字符串之間不能出現空格,如:A=a s d這樣賦值會報錯。

輸出結果:

asd
123

變量的使用

shell中直接使用$加變量名的組合即可使用變量,如:echo $A

需要注意的是:在給變量賦值時不能出現空格,如:A = 123,這樣的語法shell無法識別,必須爲:A=123,纔可以。

在這裏插入圖片描述
在這裏插入圖片描述

2.環境變量

環境變量可以在腳本內也可以在其他的腳本中使用,即在系統環境中都可以使用。

變量名 作用
$0 存儲當前腳本的名字
$n n是一個數字,存儲傳遞給腳本的迪n個變量
$# 存儲傳遞給腳本的參數的數量
$* 存儲傳遞給腳本的所有的參數
$@ 用法和$*一樣//
$? 存儲上一個命令的退出狀態,命令執行成功返回0,否則返回錯誤碼
$$ 存儲當前shell腳本所在進程的ID
$UID 存儲當前用戶ID
$PWD 存儲當前所在路徑

示例:

在這裏插入圖片描述

在這裏插入圖片描述

注:

echo -e "\033[32m"

可以修改其後的輸出字體的顏色。

echo -e "\033[0m"

結束字體顏色修改。

字體設置詳情請前往:https://blog.csdn.net/andylauren/article/details/60873400

輸出時可以使用\來進行字符轉義

3.變量的命名規則

shell的變量的命名規則基本和C是一致的,並且shell大小寫敏感。


四、語句結構

1.if條件語句

普通結構

if((num1>num2))
then
echo "$num1>$num2"
else
echo "$num1<$num2"
fi

和其他語言不同的是,shell中條件判斷分支語句不能爲空,即不能出現如下情況:

if((num1>num2))
then
echo "$num1>$num2"
else
fi

如此編譯將無法通過。

這裏有幾點須要注意:

  • if後面更的必須是雙括號(()),使用單括號會報錯,使用(())變量可以直接使用變量名來使用,而不需要通過if[][]使[]if使使[]使來引用,除此之外,if後面也可以跟[],但是[]與變量之間必須使用空格隔開,[]與if也必須使用空格分隔,且使用[]需要使用來引用變量,否則也會報錯;

使用雙括號:**

a=10
b=20
if((a>b))
then
	echo "$a > $b"
else
	echo "$a < $b"
fi

使用中括號(不使用空格分隔):
在這裏插入圖片描述
這裏有一個錯誤,即if[a>b]應該改爲if[a>a>b]。
使用中括號(使用空格分隔):

在這裏插入圖片描述

  • 一行中的多條語句須要使用;進行分隔;如:

    if((num1>num2));then
    echo "$num1>$num2"
    fi
    
  • if語句必須使用fi進行結尾,告知解釋器if語句的結束;

嵌套結構

#!/bin/bash
#by goulandis 2019.9.29

if [[ $1 -gt 90 ]];then
	echo "every good"
elif [[ $1 -gt 80 ]];then
	echo "good"
elif [[ $1 -gt 60 ]];then
	echo "pass"
else
	echo "no pass"
fi

這裏須要注意,每一個if和elif語句後面都必須跟一個then。

邏輯運算符

shell中除了可以使用“+,-,*,/,%,^,>,>=,==,<,<=,!”等編程常用的運算符外,還可以使用字母代替部分運算符。

運算符 作用
-f 判斷文件是否存在 eg: if [ -f filename ]
-d 判斷目錄是否存在 eg: if [ -d dir ]
-eq 等於,整型比較
-ne 不等於,整型比較
-lt 小於,整型比較
-gt 大於,整型比較
-le 小於或等於,整型比較
-ge 大於或等於,整型比較
-a 邏輯與 eg: 邏輯表達式 -a 邏輯表達式
-o 邏輯或 eg: 邏輯表達式 -a 邏輯表達式
-z 空字符串

如向文件中寫入內容:

在這裏插入圖片描述

第一次執行/bin/bash var.sh asd:創建文件text.txt並向文件中寫入傳入的第一個參數內容;

第二次執行/bin/bash var.sh asd:文件已存在,所以直接cat文件內容。

(())、[]、[[]]的區別

在寫shell腳本時,常碰到(())、[]、[[]],這裏來看看三者之間的區別:

符號 區別
(()) (())的作用基本和let一致,(())主要用於算術運算,比較適合進行整數比較,可以直接通過變量名來引用變量,而不需要通過$,只可以使用數學運算符“>,<,==”等進行比較;
[] []的作用與test一致,[]不支持數學運算符,只能使用字符運算符“-ge,-lt”等,[]支持“和!=”,但是“”,“!=”在[]中只能用於字符串的比較;
[[]] [[]]的功能比[]要強大,[[]]的用法和[]一樣,但是[[]]支持邏輯組合“&&,||”

小知識:

  • 用反引號包含的語句可以當作命令解釋。如:

在這裏插入圖片描述

shell解釋器會將反引號內的字符串解釋爲一個命令(如果命令有效則執行,如果無效則報錯),而不是當作字符串。

組合與&&不止可以組合邏輯表達式,還可以組合命令語句,並且組合命令語句時,當前面的語句執行失敗,後面的語句將不執行。而組合或||則是無論前面的語句是否執行成功都會執行後面的語句。

2.for循環

普通結構

j=0
for((i=1;i<=100;i++))
do
	j=`expr $i + $j`
done
echo $j

輸出結果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
5050

小知識:

  • 這裏的循環語句使用的是j=`expr $i + $j`,因爲必須告知解釋器要將expr $i + $j解釋爲命令,否則解釋器會將expr $i + $j當作是字符串。
  • expr命令的作用是求兩個數的和。
  • 在執行腳本時,添加參數-x可以查看腳本運行的過程,如:/bin/bash -x var.sh

for in結構

cd /home/goulandis/shell/tmp
dir=/home/goulandis/shell
for file in $(ls *)
do
	mv $file $dir 
done

file的值從$(ls *)中依次獲取,$file即獲取file的值; 循環語句放在do和done之間

for in結構的好處在於,可以從一個命令的輸出集合裏自動讀取集合裏的數據。、

‘’、""的區別

兩者都是爲了解決字符串中間有空格的情況,''剝奪了字符串的所有含義,在''內的任何字符都只被解釋爲字符,而""則保留了一些參數如:$、``、\。

小知識:

  • $(ls *)可以獲取當前目錄下的所有文件
  • $(ls split*)可以獲取當前目錄下的所有子目錄

3.while循環

while read line
do
	echo $line	
done < /home/goulandis/shell/var.sh

i=0

while ((i<5))
do
	echo $i
	((i++))	
done

輸出語句:

#!/bin/bash
#by goulandis 2019.9.28

while read line
do
echo $line
done < /home/goulandis/shell/var.sh

i=0
while ((i<5))
do
echo $i
((i++))
done
0
1
2
3
4
  • while之後可以跟命令語句(如:reas line),也可以更邏輯表達式(如:i<5),但是邏輯表達式必須使用(())括起來,並且while的遞增變量也必須使用(())括起來。
  • for一樣,while的循=循環體必須放在do done之間。

小知識:

  • read命令配合< 文件名可以讀取文件裏的內容。如:讀取host.txt文件的第二列的內容

    文件內容:

1 Alian man 176
2 Goulandis faleman 168
3 Dekes man 188

​ 操作代碼:

while read line
do
	name=`echo $line | awk '{print $2}'`
	echo -e "\033[32mName:$name\033[0m"
done <host.txt

​ 讀取結果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
Name:Alian
Name:Goulandis
Name:Dekes

4.until循環

i=5
until [[ i -lt 0 ]]
do
	echo $i
	((i--))
done

輸出結果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
5
4
3
2
1
0

while當滿足條件時執行不同的是,until是當滿足條件時退出;

和所有循環體一樣,until的循環體也放在do done中。

5.case條件語句

case $1 in
	apache)
	echo "Install Apache"
	;;
	mysql)
	echo "Install mysql"
	;;
	php)
	echo "Install php"
	;;
	*)
	echo "usage:{$0 apache|mysql|php|help}"
	;;
esac 
  • case語句必須使用esac標識語句結束
  • 每一個分支的匹配值後面是必須跟一個)
  • 每一個分支也必須使用;;進行分隔
  • 不像C++中的switch語句沒有break不跳出而繼續向下執行,shell中的case語句執行完分支後會自動跳出
  • *表示當分支中沒有能比配的值時,就匹配*這個分支

6.select語句

select語句的主要功能就是自動生成一個選擇菜單

PS3="select application number:"

select i in "apache" "mysql" "php"
do
	case $i in
		apache)
		echo "install apache"
		;;
		mysql)
		echo "install mysql"
		;;
		php)
		echo "install php"
		;;
		*)
		echo "usage:{input 1|2|3|help}"
	esac
done

輸出結果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
1) apache
2) mysql
3) php
select application number:1
install apache

  • in後面可以跟一系列的鍵值集合,每個鍵值之間使用空格分隔
  • shell預定義了變量PS3(大寫的PS3)用於輸入描述,如:輸出結果中的select application number:
  • selectcase搭配能形成十分友好的選擇界面
  • select的語句體也必須放在do done中間

五、數組

1.一維數組

數組定義

A=(1 2 3)

數組使用

echo ${A[0]}

shell的數組也是從0號索引開始

幾種數組的常用方法

方法 作用
${A[@]}或${A[*]} 顯示所有元素
${#A[@]} 統計數組的參數個數
${A[@]/1/a} 替換數組元素
unset A[n] 刪除數組中第n個元素

數組的賦值

直接初始化時賦值

A=(
	apache
	mysql
	php
)

一個元素一個元素的賦值

#A=()可寫也可不寫
A=()
A[0]=0
A[1]=1

六、函數

函數定義

function command()
{
#函數體
}

函數調用

command 參數列表

參數列表按順序依次對應$1,$2,$3等,如:

function command()
{
	if [[ (! -z $1) && (! -z $2) ]]
	then
		echo $1 $2
	fi
}

command param1 param2

輸出結果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
param1 param2

這裏要注意使用&&時一個邏輯表達式需要用()括起來,否則&&會將$1進行&&運算。

函數的返回值

函數用return來返回值,但是return只能用於返回整型,返回字符串需要用echo。如:

#返回數字-方法1
function command()
{
	if(($1==1));then
		return $1
	else
		echo $1
	fi
}
command 1
echo $?
#返回數字-方法2
echo $command 1
#返回字符串-方法1
echo $(command asd)
#返回字符串-方法2
echo `command sdf`

輸出結果:

goulandis@ubuntu:~/shell$ /bin/bash var.sh
1
1
asd
sdf

$?接收上一句命令的返回值。

小知識:

read -p "輸入描述" cmd命令可以記錄命令命令行的輸入到cmd變量中,如:

goulandis@ubuntu:~/shell$ read -p "Input parameter:" cmd
Input parameter:this a command
goulandis@ubuntu:~/shell$ echo $cmd
this a command


七、shell命令

1.sed命令

示例:對如下sed.txt文件進行修改

#by auther 2019.9.30 txt

ip 192.168.9.120
ip 192.168.5.5
ip 168.1.2.111

those my ip

替換字符串

sed -i 's/auther/goulandis/g' sed.txt

輸出結果:

#by goulandis 2019.9.30 txt
 
ip 192.168.9.120
ip 192.168.5.5
ip 168.1.2.111

those my i

sed.txt中的所有auther字符串替換成字符串goulandis,其中開頭的s和結尾的g是必須寫的,這是固定格式,並且參數-i也是必須寫的,如果不使用參數-ised只會修改緩衝區中的數據,而不會修改sed.txt源文件中的內容。

在行首/行尾插入

sed -i 's/^/&line /g' sed.txt

輸出結果:

line #by goulandis 2019.9.30 txt
line 
line ip 192.168.9.120
line ip 192.168.5.5
line ip 168.1.2.111
line 
line those my ip

sed.txt的每行行首插入字符串line,行首匹配規則使用的是正則表達式,若需要在行尾插入,命令爲sed -i 's/$/&字符串/g' sed.txt

在前一行或後一行插入

sed -i '/192.168.9.120/a line ip 192.168.9.9' sed.txt

輸出結果:

line #by goulandis 2019.9.30 txt
line 
line ip 192.168.9.120
line ip 192.168.9.9
line ip 192.168.5.5
line ip 168.1.2.111
line 
line those my ip

sed.txt192.168.9.120所在行的後面一行插入字符串line ip 192.168.9.9,這裏要注意,這個命令不再寫前面的s和後面的g,如果要在前面一行插入,則將a替換成i

打印固定行數的內容

sed -n '1,3p' sed.txt

輸出結果:

line #by goulandis 2019.9.30 txt
line 
line ip 192.168.9.120

打印sed.txt中第一行到第三行的內容,其中p是必須寫的 ,打印首行和尾行sed -n '1p;$p' sed.txt

這裏要注意,'1,$p'表示從首行到尾行,有多行,'1p;$p'表示首行和尾行,只有兩行。

2.find命令

尋找文件

find . -name "sed.txt"

在當前目錄下尋找文件sed.txt

find . -maxdepth 1 -name "sed.txt"

在當前目錄一級目錄下搜索sed.txt文件,即不向子目錄搜索。

find . -maxdepth 1 -type f -name "*.txt" -mtime -1

在當前目錄一級目錄下搜索類型爲文件,修改時間爲1天前的txt文件。

find . -maxdepth 1 -type f -name "*.txt" -mtime -1 -exec rm -rf {} \;

在當前目錄一級目錄下搜索類型爲文件,修改時間爲1天前的txt文件並刪除這些文件。-exec表示將前面搜索到的內容放到{}中。其中\;是必須的固定格式。-xargs的作用和-exec基本一樣,只是-xargs不能配合cpmv命令使用。

3.grep命令

搜索固定內容的行

grep "ip" sed.txt

輸出結果:

line ip 192.168.9.120
line ip 192.168.9.9
line ip 192.168.5.5
line ip 168.1.2.111
line those my ip

使用參數-v表示反義,如:grep -v "ip" sed.txt,表示搜索不包含ip的行。-n可以將行號一併打印出來。

grep "120$" sed.txt

搜索以120結尾的行,開頭使用"^line"""中寫入正則表達式,即可按正則表達式來搜索內容。

4.awk命令

打印列

awk '{print "註解:" $1}' sed.txt

打印第一列的內容,列之間需要用空格分隔,否則將識別成一列,$n表示第n列。$NF表示最後一列,""中可以在輸出內容前添加任何註解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章