SRE雲端計算運維之基礎篇二:許可權管理,VIM工具,檔案查詢及shell基礎

三两螺蛳粉發表於2024-11-10

目錄

  • 檔案許可權管理
  • 訪問控制列表ACL
  • VIM的使用及內容查詢
  • 文字三劍客
  • 基本正則和擴充套件正則
  • shell指令碼之變數

簡單總結一下linux中的許可權

1.首先介紹一下關於linux中的使用者:
Linux中每個使用者是透過 User Id (UID)來唯一標識的,且Linux中可以將一個或多個使用者加入使用者組中,使用者組是透過Group ID(GID) 來唯一標識的。在這其中我們需要明白使用者和組之間的關係。

  • 使用者的主要組(primary group):使用者必須屬於一個且只有一個主組,預設建立使用者時會自動建立
    和使用者名稱同名的組,做為使用者的主要組,由於此組中只有一個使用者,又稱為私有組
  • 使用者的附加組(supplementary group): 一個使用者可以屬於零個或多個輔助組,附屬組
    2.使用者和組的主要配置檔案:
* /etc/passwd:使用者及其屬性資訊(名稱、UID、主組ID等)
* /etc/shadow:使用者密碼及其相關屬性
* /etc/group:組及其屬性資訊
* /etc/gshadow:組密碼及其相關屬性

passwd檔案格式:

etc/passwd
* login name:登入用名(wang)
* passwd:密碼 (x)
* UID:使用者身份編號 (1000)
* GID:登入預設所在組編號 (1000)
* GECOS:使用者全名或註釋
* home directory:使用者主目錄 (/home/wang)
* shell:使用者預設使用shell (/bin/bash)

gshdow檔案格式:

etc/gshdow
* 群組名稱:就是群的名稱
* 群組密碼:
* 組管理員列表:組管理員的列表,更改組密碼和成員
* 以當前組為附加組的使用者列表:多個使用者間用逗號分隔

shadow檔案格式:

etc/shadow
* 登入用名
* 使用者密碼:一般用sha512加密
* 從1970年1月1日起到密碼最近一次被更改的時間
* 密碼再過幾天可以被變更(0表示隨時可被變更)
* 密碼再過幾天必須被變更(99999表示永不過期)
* 密碼過期前幾天系統提醒使用者(預設為一週)
* 密碼過期幾天後帳號會被鎖定
* 從1970年1月1日算起,多少天后帳號失效

3.使用者和組管理常用命令
使用者管理命令:

* useradd:新增使用者
* usermod:修改使用者屬性
* userdel:刪除使用者

格式:

user[options] [options] username
useradd -r  -u 1001 mqh #新增使用者
usermod -u 1002 mqh #修改使用者屬性
userdel -f mqh #刪除使用者

新增使用者常見選項

-u UID 
-o 配合-u 選項,不檢查UID的唯一性
-g GID 指明使用者所屬基本組,可為組名,也可以GID
-c "COMMENT“ 使用者的註釋資訊
-d HOME_DIR 以指定的路徑(不存在)為家目錄
-s SHELL 指明使用者的預設shell程式,可用列表在/etc/shells檔案中
-G GROUP1[,GROUP2,...] 為使用者指明附加組,組須事先存在
-N 不建立私用組做主組,使用users組做主組
-r 建立系統使用者 CentOS 6之前: ID<500,CentOS7 以後: ID<1000
-m 建立家目錄,用於系統使用者
-M 不建立家目錄,用於非系統使用者
-p 指定加密的密碼

修改使用者屬性常見選項:

-u UID: 新UID
-g GID: 新主組
-G GROUP1[,GROUP2,...[,GROUPN]]]:新附加組,原來的附加組將會被覆蓋;若保留原有,則要同時使用-a選項
-s SHELL:新的預設SHELL
-c 'COMMENT':新的註釋資訊
-d HOME: 新家目錄不會自動建立;若要建立新家目錄並移動原家資料,同時使用-m選項
-l login_name: 新的名字
-L: lock指定使用者,在/etc/shadow 密碼欄的增加 ! 
-U: unlock指定使用者,將 /etc/shadow 密碼欄的 ! 拿掉
-e YYYY-MM-DD: 指明使用者賬號過期日期
-f INACTIVE: 設定非活動期限,即寬限期

刪除使用者常見選項:

-f, --force   強制
-r, --remove 刪除使用者家目錄和郵箱

組命令


* groupadd
* groupmod
* groupdel
group[options] [options] groupname
groupadd -g  -r 1001 mqh #新增組
groupmod -g 1002 mqh #修改組屬性
groupdel -f mqh #刪除組

組的常用選項

組的常用選項
#建立
-g GID 指明GID號;
-r 建立系統組,CentOS 6之前: ID<500,CentOS 7以後: ID<1000
#修改
-n group_name: 新名字
-g GID: 新的GID
#刪除
-f, --force 強制刪除,即使是使用者的主組也強制刪除組,但會導致無主組的使用者不可用無法登入

新增/修改使用者密碼

passwd [options] username
echo -e '123456\n123456' | passwd mqh #非互動式修改密碼(\n表換行)

常見選項

-d:刪除指定使用者密碼
-l:鎖定指定使用者
-u:解鎖指定使用者
-e:強制使用者下次登入修改密碼
-f:強制操作
-n mindays:指定最短使用期限
-x maxdays:最大使用期限
-w warndays:提前多少天開始警告
-i inactivedays:非活動期限
--stdin:從標準輸入接收使用者密碼,Ubuntu無此選項

檢視使用者相關id資訊

`id [OPTION]  username`
常見選項

-u: 顯示UID
-g: 顯示GID
-G: 顯示使用者所屬的組的ID
-n: 顯示名稱,需配合ugG使用

檔案許可權管理

程式訪問檔案時的許可權,取決於此程式的發起者。

  • 程序的發起者,同檔案的屬主:則應用檔案屬主許可權
  • 程序的發起者,屬於檔案屬組;則應用檔案屬組許可權
  • 應用檔案“其它”許可權
    檔案許可權說明
    舉例:-rwxrw----
    從右往左看,一共10個字元,分成三段,第一段“---”代表的是“o”及other,表其他組和使用者,第二段“rw-”代表的是“g”及group,表檔案所屬的組,第三段“rwx”代表的是“u”及owner,表檔案所屬的主(使用者),第四段“-”代表檔案型別。
r Readable 4
w Writable 2
x eXcutable 1

對檔案的許可權:

  • r 可使用檔案檢視類工具,比如:cat,可以獲取其內容
  • w 可修改其內容,檔案的是否被刪除和檔案的許可權無關
  • x 可以把此檔案提請核心啟動為一個程序,即可以執行(執行)此檔案(此檔案的內容必須是可執行)
    檔案許可權常見組合
--- 0
r   4
r-x 5 
rw  6
rwx 7

數學法的許可權:
八進位制數學

--- 000 0
--x 001 1
-w- 010 2
-wx 011 3
r-- 100 4
r-x 101 5
rw- 110 6
rwx 111 7

舉例:

rw-r----- 640 
rwxr-xr-x 755

設定檔案的所有者chown

chown [user]:[group] file

設定檔案的屬組資訊chgrp

chgrp [group] file

修改檔案許可權chmod

chmod -R a+x file # -R遞迴修改許可權 a+x:屬主加上X許可權,修改指定一類使用者某個或某個許可權
chmod -R u=rwx file #修改指定一類使用者的所有許可權 
chmod 777 file # 777:rwx

訪問控制列表ACL

ACL:Access Control List,實現靈活的許可權管理
除了檔案的所有者,所屬組和其它人,可以對更多的使用者設定許可權。
ACL生效順序:所有者,自定義使用者,所屬組|自定義組,其他人
1.ACL相關命令
setfacl 用於設定檔案或目錄的ACL

setfacl -m u:meng:rwx file3.txt #u:meng:rwx 代表修改meng使用者的u許可權

getfacl 可檢視設定的ACL許可權

getfacl file3.txt


從上圖可以看出使用setfacl後再ll,可以發現檔案許可權出現了一些小變化,多了一個加號,加號代表額外的ACL規則。而且從現有的發現來看,我們修改的是u許可權,按理來說-rw-r--r--應該變成-rwxr--r--,但事實並非如此。原因是:ls -l 命令顯示的基本許可權位只反映了檔案的基本許可權,而不是ACL設定的許可權。即使使用 setfacl 修改了某個使用者的許可權,基本許可權位不會自動更新為反映ACL的變化。所以這個時候可以使用getfacl來檢視這個檔案的ACL規則。

2.mask許可權
mask 是一個特殊的ACL條目,它定義了所有使用者和組的許可權上限。換句話說,mask 決定了哪些許可權可以被實際應用於檔案或目錄,即使ACL中設定了某些許可權,如果這些許可權超出了mask的範圍,它們將不會生效。作用:用於限制所有使用者和組的許可權上限。

setfacl -m m:r-x file3.txt #無論之後再修改成什麼許可權,最終只有r-x生效

VIM的使用及內容查詢

vim file  #按 i 進入編輯模式
vim基本命令
按“:”進入Ex模式 ,建立一個命令提示符: 處於底部的螢幕左側
:w 寫(存)磁碟檔案
:wq 寫入並退出
:x 寫入並退出
:X   加密
:q 退出
:q! 不存檔退出,即使更改都將丟失 
:r   filename 讀檔案內容到當前檔案中
:w   filename 將當前檔案內容寫入另一個檔案
:!command 執行命令
:r!command 讀入命令的輸出

檔案內容查詢

cat命令
cat [options] file
常用選項
-n:顯示行號
-b:顯示非空行的行號
-E:在每行末尾顯示 $
head和tail命令
head [options] file
常用選項
-c # 指定獲取前#位元組
-n # 指定獲取前#行,#如果為負數,表示從檔案頭取到倒數第#前

範例:
[root@localhost meng]# head -c 10 passwd2 
root:x:0:0
[root@localhost meng]# head -n 3 passwd2 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

tail [options] file
常用選項
-c # 指定獲取後#位元組
-n # 指定獲取後#行,如果#是負數,表示從第#行開始到檔案結束
-f 跟蹤顯示檔案新追加的內容,常用於日誌監控

範例:
[root@localhost meng]# tail -c 10 passwd2 
n/nologin
[root@localhost meng]# tail -n 3 passwd2 
sssd:x:997:994:User for sssd:/:/sbin/nologin
chrony:x:996:993::/var/lib/chrony:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

wc命令
wc [options] file
常用選項
-l 只計數行數
-w 只計數單詞總數
-c 只計數字節總數
-m 只計數字符總數
-L 顯示檔案中最長行的長度

範例:
[root@localhost meng]# cat file2.txt 
hello 我的
cat: /xxx: No such file or directory
[root@localhost meng]# wc -l file2.txt 
2 file2.txt
[root@localhost meng]# wc -w file2.txt 
9 file2.txt
[root@localhost meng]# wc -c file2.txt 
50 file2.txt
[root@localhost meng]# wc -m file2.txt 
46 file2.txt
[root@localhost meng]# wc -L file2.txt 
36 file2.txt

cut命令
cut [options] file
常用選項:
-b list:按位元組位置提取資料。例如 1-3 表示第 1 到第 3 位元組
-c list:按字元位置提取資料。用法與 -b 類似(對於多位元組字元更準確)。
-d delimiter:指定欄位分隔符
-f list:按欄位提取資料。例如 1-3 表示第 1 到第 3 欄位
-s:只處理包含分隔符的行。 

範例:
[root@localhost meng]# cat file6.txt 
apple,banana,pear
red,bule,green
cat,dog,bird

[root@localhost meng]# cut -b 1-4 file6.txt 
appl
red,
cat,

[root@localhost meng]# cut -d"," -f 1-2 file6.txt 
apple,banana
red,bule
cat,dog

文字查詢

locate命令
介紹:
locate 是透過查詢系統上預建的檔案索引資料庫 /var/lib/mlocate/mlocate.db來查詢檔案的,想要使用locate或者find命令,首先需要安裝mlocate包,安裝完後執行updatedb更新資料庫。索引構建過程需要遍歷整個根檔案系統,很消耗資源,所以執行updatedb的時候需要系統較為空閒時自動進行。

[root@localhost meng]# yum install mlocate
[root@localhost meng]# updatedb
[root@localhost meng]# ll /var/lib/mlocate/mlocate.db
rw-r----- 1 root slocate 869840 11月  7 06:54 /var/lib/mlocate/mlocate.db

特點:

  • 查詢速度快
  • 模糊查詢
  • 非實時查詢(新建立or刪除的檔案無法查詢)
  • 搜尋的是檔案的全路徑,不僅僅是檔名
  • 僅支援搜尋使用者具備讀取和執行許可權的目錄
locate命令
locate [options] [PATTERN]

常用選項:
-i 不區分大小寫的搜尋
-n N 只列舉前N個匹配專案
-r 使用基本正規表示式

範例:
[root@localhost meng]# locate -n 4 conf
/boot/config-4.18.0-348.el8.0.2.x86_64
/boot/grub2/i386-pc/configfile.mod
/boot/loader/entries/9eb148c7e35a4fcfbe73a10cc3ad2551-0-rescue.conf
/boot/loader/entries/9eb148c7e35a4fcfbe73a10cc3ad2551-4.18.0-348.el8.0.2.x86_64.conf

find命令
介紹:
find 是實時查詢工具,透過遍歷指定路徑完成檔案查詢。

特點:

  • 查詢速度略慢
  • 精確查詢
  • 實時查詢
  • 查詢條件豐富
  • 僅支援搜尋使用者具備讀取和執行許可權的目錄

格式:
find [OPTION] [查詢路徑] [查詢條件] [處理動作]
查詢路徑:指定具體目標路徑;預設為當前目錄
查詢條件:指定的查詢標準,可以檔名、大小、型別、許可權等標準進行;預設為找出指定路徑下的所
有檔案
處理動作:對符合條件的檔案做操作,預設輸出至螢幕

find根據檔名和inode查詢
find [options] [PATTERN]

常用選項:
-name "檔名稱" #支援使用glob,如:*, ?, [], [^],萬用字元要加雙引號引起來
-iname "檔名稱"  #不區分字母大小寫
-inum n #按inode號查詢

範例:
[root@localhost meng]# find /home/meng/ -name "*.txt"
/home/meng/file1.txt
/home/meng/file2.txt
/home/meng/file3.txt
/home/meng/filea.txt
/home/meng/fileb.txt
/home/meng/filec.txt
/home/meng/filed.txt
/home/meng/file4.txt
[root@localhost meng]# find / -name "file1.txt"
/home/mqh/file1.txt
/home/meng/file1.txt
[root@localhost meng]# find -name "file1.txt"
./file1.txt

find根據屬主、屬組查詢
常用選項:
-user  #查詢屬主為指定使用者(UID)的檔案
-group  #查詢屬組為指定組(GID)的檔案
-uid  #查詢屬主為指定的UID號的檔案
-gid #查詢屬組為指定的GID號的檔案
-nouser #查詢沒有屬主的檔案
-nogroup #查詢沒有屬組的檔案

範例:
[root@localhost meng]# find / -user meng
find: ‘/proc/2031/task/2031/fd/7’: No such file or directory
find: ‘/proc/2031/task/2031/fdinfo/7’: No such file or directory
find: ‘/proc/2031/fd/6’: No such file or directory
find: ‘/proc/2031/fdinfo/6’: No such file or directory
/var/spool/mail/meng
/home/meng
/home/meng/.bash_logout
/home/meng/.bash_profile
/home/meng/.bashrc
/home/meng/file2.txt
/home/meng/file3.txt
/home/meng/.bash_history

find根據檔案型別查詢
-type TYPE

常用選項:
TYPE可以是以下形式:
f: 普通檔案
d: 目錄檔案
l: 符號連結檔案
s:套接字檔案
b: 塊裝置檔案
c: 字元裝置檔案
p: 管道檔案

範例:
[root@localhost meng]# ll /home
總用量 0
drwx------ 2 meng        meng 256 10月 31 10:51 meng
drwx------ 2 mengqinghui meng  62 10月 31 09:03 mengqinghui
drwxr-xr-x 2 root        root 157 10月 26 10:08 mqh
[root@localhost meng]# find /home -type d -ls
 16786460      0 drwxr-xr-x   5  root     root           48 10月 31 09:03 /home
 33582862      0 drwxr-xr-x   2  root     root          157 10月 26 10:08 /home/mqh
   711371      0 drwx------   2  meng     meng          256 10月 31 10:51 /home/meng
 16786453      0 drwx------   2  mengqinghui meng           62 10月 31 09:03 /home/mengqinghui

根據檔案大小來查詢
範例:
[root@localhost meng]# find -size +2k
./.file4.txt.swp
[root@localhost meng]# find -size -1M
./filea.txt
./fileb.txt
./filec.txt
./filed.txt

文字三劍客

grep命令

工作模式:
由正規表示式字元及文字字元所編寫的過濾條件來幫助使用者對目標文字進行匹配檢查,並列印到行。

grep命令
格式:
grep [OPTIONS] PATTERN [FILE...]

常用選項:
--color=auto 對匹配到的文字著色顯示
-m  # 匹配#次後停止
-v 顯示不被pattern匹配到的行,即取反
-i 忽略字元大小寫
-n 顯示匹配的行號
-c 統計匹配的行數
-o 僅顯示匹配到的字串
-q 靜默模式,不輸出任何資訊
-A # after, 後#行
-B # before, 前#行
-C # context, 前後各#行
-e 實現多個選項間的邏輯or關係
-w 匹配整個單詞
-E 使用ERE,相當於egrep(擴充套件正規表示式)
-F 不支援正規表示式,相當於fgrep
-P 支援Perl格式的正規表示式
-f file 根據模式檔案處理
-r   遞迴目錄,但不處理軟連結
-R   遞迴目錄,但處理軟連結

範例:

#匹配hello字元
[root@localhost meng]# cat file2.txt 
hello 我的
cat: /xxx: No such file or directory
[root@localhost meng]# grep -w hello file2.txt 
hello 我的

#查詢80埠
[root@localhost meng]# ps aux | grep 80
polkitd      903  0.0  0.6 1766344 24080 ?       Ssl  06:24   0:00 /usr/lib/polkit-1/polkitd --no-debug
root         918  0.0  1.0 438880 41076 ?        S    06:24   0:00 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --logger=files
root         922  0.0  0.1  92624  7580 ?        Ss   06:24   0:00 /usr/lib/systemd/systemd-logind
root        2104  0.0  0.0 221928  1120 pts/0    S+   08:24   0:00 grep --color=auto 80

#查詢並列印本機ip地址
[root@localhost meng]# ifconfig ens33 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'|head -1
192.168.93.200

sed命令
工作模式:
1.讀取輸入流裡的一行,將其儲存在模式空間中。
2.依次執行一個或多個操作命令,如替換,刪除,插入等。
3.根據第二步的操作結果,對模式空間內的內容進行修改。
4.輸入模式空間的內容。
5.處理完當前行後,清空模式空間,準備處理下一行。

舉例說明:

[root@localhost meng]# cat file5.txt 
"小米" phone
“蘋果” phone
“華為” phone
“錘子” phone
[root@localhost meng]# sed -e 's/小米/蘋果/g' -e '/蘋果/d' file5.txt 
“華為” phone
“錘子” phone

根據sed的工作模式可得:
1.讀取第一行 "小米" phone,模式空間裡的內容為"小米" phone
2.執行's/小米/蘋果/g'命令,及將所有的小米替換為蘋果,模式空間內的內容就變成了 “蘋果” phone
3.執行下一個操作命令'/蘋果/d',及刪除包含蘋果的行
4.輸出模式空間的內容(空的,之前的步驟刪掉蘋果了)
5.清空模式空間
6.繼續讀取下一行“華為” phone,模式空間裡的內容為"華為" phone
7.執行's/小米/蘋果/g'命令,內容不匹配,所有原本的內容不變
8.輸出模式空間的內容,“華為” phone
9.繼續讀取下一行。。。
sed命令
格式:
sed [option]... 'script;script;...' [inputfile...]

常用選項:
-n      不輸出模式空間內容到螢幕,即不自動列印
-e      允許使用多個編輯命令
-f FILE 從指定檔案中讀取編輯指令碼
-r, -E  使用擴充套件正規表示式
-i      直接修改
-i.bak  備份檔案並原處編輯
-s      將多個檔案視為獨立檔案,而不是單個連續的長檔案流

替換命令:
s/old/new/:將每一行中的第一個匹配項替換為新文字
s/old/new/g:將每一行中的所有匹配項替換為新文字
s/old/new/2:將每一行中的第二個匹配項替換為新文字
s/old/new/p:列印替換後的行

範例:
[root@localhost meng]# cat file5.txt 
"小米" “紅米” '紅米' phone
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed 's/小米/華為/' file5.txt 
"華為" “紅米” '紅米' phone
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed 's/紅米/錘子/g' file5.txt 
"小米" “錘子” '錘子' phone
"華為" “榮耀” ‘錘子’ '錘子' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed 's/紅米/apple/2' file5.txt 
"小米" “紅米” 'apple' phone
"華為" “榮耀” ‘紅米’ 'apple' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'


插入命令:
i\:在匹配行之前插入文字
a\:在匹配行之後附加文字
c\:將匹配行替換為指定文字

範例:
[root@localhost meng]# cat file5.txt 
"小米" “紅米” '紅米' phone
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed '/小米/i\在小米之前插入雷軍' file5.txt
在小米之前插入雷軍
"小米" “紅米” '紅米' phone
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed '/小米/a\在小米之後插入雷軍' file5.txt
"小米" “紅米” '紅米' phone
在小米之後插入雷軍
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed '/紅米/c\將包含紅米的行替換雷軍' file5.txt
將包含紅米的行替換雷軍
將包含紅米的行替換雷軍
“蘋果” “apple” phone
“錘子” phone
'錘子'


刪除命令:
d:刪除匹配的行
1d:刪除第一行
1,3d:刪除第1到第3行

範例:
[root@localhost meng]# cat file5.txt 
"小米" “紅米” '紅米' phone
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed '/錘子/d' file5.txt 
"小米" “紅米” '紅米' phone
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
[root@localhost meng]# sed '1d' file5.txt 
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# sed '1,3d' file5.txt 
“錘子” phone
'錘子'

awk命令
awk工作模式:
1.讀取一行
每次讀取輸入流中的一行,並將其儲存在內部緩衝區中。

2.分割欄位
預設使用空格或製表符作為欄位分隔符,將每一行分割成多個欄位,可以使用-F 選項或 FS 變數指定其他分隔符。

3.執行規則
依次執行在指令碼中定義的規則。每個規則由一個模式和一個操作組成,格式為 pattern { action },如果模式匹配當前行,則執行相應的操作。

4.處理內建變數
awk 提供了一些內建變數,用於訪問和操作欄位、行號等資訊。

5.輸出結果

awk命令
常見內建變數:
$0:當前行的全部內容。
$1, $2, ...:當前行的第一個欄位、第二個欄位等。
NF:當前行的欄位數。
NR:當前行的行號。
FS:欄位分隔符。
OFS:輸出欄位分隔符,預設為空格。
ORS:輸出行分隔符,預設為換行符。

[root@localhost meng]# cat file6.txt 
apple,banana,pear
red,bule,green
cat,dog,bird
[root@localhost meng]# awk -F, '{print $0}' file6.txt 
apple,banana,pear
red,bule,green
cat,dog,bird
[root@localhost meng]# awk -F, '{print $1}' file6.txt 
apple
red
cat
[root@localhost meng]# awk -F, '{print $0,NF}' file6.txt 
apple,banana,pear 3
red,bule,green 3
cat,dog,bird 3
[root@localhost meng]# awk -F, '{print NR,$0}' file6.txt 
1 apple,banana,pear
2 red,bule,green
3 cat,dog,bird

awk特殊規則

BEGIN:在處理任何輸入行之前執行的程式碼塊。
END:在處理所有輸入行之後執行的程式碼塊。

範例:
[root@localhost meng]# awk -F, 'BEGIN{ print "在處理檔案前列印我" } { print $0 }' file6.txt 
在處理檔案前列印我
apple,banana,pear
red,bule,green
cat,dog,bird
[root@localhost meng]# awk -F, '{ print $0 } END{ print "總行數:",NR }' file6.txt 
apple,banana,pear
red,bule,green
cat,dog,bird
總行數: 3

awk的常見action
print命令

作用:輸出指點內容
範例:
[root@localhost meng]# awk '{ print $0 }' file5.txt 
"小米" “紅米” '紅米' phone
"華為" “榮耀” ‘紅米’ '紅米' phone
“蘋果” “apple” phone
“錘子” phone
'錘子'
[root@localhost meng]# awk '{ print $1 }' file5.txt 
"小米"
"華為"
“蘋果”
“錘子”
'錘子'

printf命令

用途:格式化輸出。

格式符:
%s:顯示字串
%d, %i:顯示十進位制整數
%f:顯示為浮點數
%e, %E:顯示科學計數法數值 
%c:顯示字元的ASCII碼
%g, %G:以科學計數法或浮點形式顯示數值
%u:無符號整數
%%:顯示%自身

格式修飾符:
-   左對齊(預設右對齊) 
+   顯示數值的正負符號   
寬度:指定輸出的最小寬度。
例如:%-10s 表示左對齊,寬度為10。
精度:對於浮點數,指定小數點後的位數。
例如:%.2f 表示保留兩位小數。
前導零:指定輸出的最小寬度,並用零填充。
例如:%05d 表示寬度為5,不足部分用零填充。

範例:
[root@localhost meng]# cat file7.txt 
apple,100,0.999
banana,2,1.5
pear,30,2.50
[root@localhost meng]# awk -F, '{ printf "字串: %s, 數字: %d\n", $1,$2 }' file7.txt 
字串: apple, 數字: 100
字串: banana, 數字: 2
字串: pear, 數字: 30
[root@localhost meng]# awk -F, '{ printf "字串: %s, 數字: %.3f\n", $1,$3 }' file7.txt 
字串: apple, 數字: 0.999
字串: banana, 數字: 1.500
字串: pear, 數字: 2.500
[root@localhost meng]# awk -F, '{ printf "%-10s %5d %8.2f\n", $1,$2,$3 }' file7.txt 
apple        100     1.00
banana         2     1.50
pear          30     2.50
[root@localhost meng]# awk -F, '{ printf "字串: %s, 數字: %d%%\n", $1,$2 * 10 }' file7.txt 
字串: apple, 數字: 1000%
字串: banana, 數字: 20%
字串: pear, 數字: 300%

變數賦值

用途:給變數賦值。
範例:
[root@localhost meng]# cat file7.txt 
apple,100,0.999
banana,2,1.5
pear,30,2.50
10,20,30
[root@localhost meng]# awk -F, '{ sum += $2 } END { print "sum:",sum }' file7.txt 
sum: 152

if-else語句

作用:條件判斷
範例:
[root@localhost meng]# cat file7.txt 
apple,100,0.999
banana,2,1.5
pear,30,2.50
10,20,30

#輸出符合第2列大於20的所有行
[root@localhost meng]# awk -F, '{ if($2 > 20) print $0 }' file7.txt 
apple,100,0.999
pear,30,2.50

#輸出符合第2列大於20的所有行裡的第一行
[root@localhost meng]# awk -F, '{ if($2 > 20) print $1 }' file7.txt 
apple
pear

[root@localhost meng]# awk -F, '{ if($2 > 2000) {print $0} else { print $1} }' file7.txt 
apple
banana
pear
10
[root@localhost meng]# awk -F, '{ if($2 > 0) {print $0} else { print $1} }' file7.txt 
apple,100,0.999
banana,2,1.5
pear,30,2.50
10,20,30

switch 語句

作用:根據多個條件選擇執行不同的操作
範例:
[root@localhost meng]# cat file7.txt 
apple,100,0.999
banana,2,1.5
pear,30,2.50
10,20,30
[root@localhost meng]# awk -F, '{ switch ($1) { case "apple": print "這是一個蘋果";break; case "10": print "這是個數字";break; default: print "未識別";} }' file7.txt 
這是一個蘋果
未識別
未識別
這是個數字

迴圈語句

迴圈語句之for迴圈
作用:重複執行一組操作
範例:
#逐個輸出每一行的所有欄位
[root@localhost meng]# awk -F, '{ for (i = 1; i <= NF; i++) print $i; }' file7.txt 
apple
100
0.999
banana
2
1.5
pear
30
2.50
10
20
30

[root@localhost meng]# tail -n 1 file7.txt 
10,20,30
[root@localhost meng]# tail -n 1 file7.txt | awk -F, '{sum=0; for(i=1;i<=NF;i++){sum+=$i}; print sum}'
60
解讀:sum初始為0,當i=1時,其所代表的第一個欄位(就是10),將10賦值給sum,
此時sum為10而不是1,以此類推sum=i1+i2+i3 也就是sum=10+20+30

迴圈語句之while迴圈
作用:在條件為真時重複執行一組操作
範例:
[root@localhost meng]# cat file7.txt 
apple,100,0.999
banana,2,1.5
pear,30,2.50
10,20,30

[root@localhost meng]# awk -F, '{ i = 100; while (i <= NF) { print $i; i++; } }' file7.txt 
[root@localhost meng]# awk -F, '{ i = 1; while (i <= NF) { print $i; i++; } }' file7.txt 
apple
100
0.999
banana
2
1.5
pear
30
2.50
10
20
30
[root@localhost meng]# awk -F, '{ print NF }' file7.txt 
3
3
3
3

解讀:已知,file7檔案裡共有4行,每行有三個欄位,i的初始為1,
當 i = 1時,while判斷為真,依次輸出每一行裡的所有欄位,當i的值超過3時,while判斷為假,不再執行while迴圈。

do-while迴圈
作用:先執行一次do操作,然後再檢查條件
範例:
[root@localhost meng]# awk -F, '{ i = 1; do { print $i; i++; } while (i <= NF); }' file7.txt 
apple
100
0.999
banana
2
1.5
pear
30
2.50
10
20
30

特殊控制語句

next語句
作用:跳過當前行,繼續執行下一行
範例:
[root@localhost meng]# cat file7.txt 
apple,100,0.999
banana,2,1.5
next,”跳過我這行“
pear,30,2.50
10,20,30
[root@localhost meng]# awk -F, '{ if ($1 == "next") next; print $0; }' file7.txt
apple,100,0.999
banana,2,1.5
pear,30,2.50
10,20,30

exit語句
作用:立即退出awk指令碼
範例:
[root@localhost meng]# cat file7.txt 
apple,100,0.999
stop,”遇到我你就得停了喔“
banana,2,1.5
next,”跳過我這行“
pear,30,2.50
10,20,30
[root@localhost meng]# awk -F, '{ if ($1 == "stop") exit; print $0; }' file7.txt
apple,100,0.999

基本正則和擴充套件正則

基本正規表示式常用用法包括:字元匹配、匹配次數、位置錨定和分組
字元匹配

-v : 反向匹配
.:匹配任意單個字元
[  ]:匹配括號內的任意一個字元
[ ^ ]:匹配不在括號內的任意一個字元
[ - ]:匹配指定範圍內的任意一個字元
[:alnum:] 字母和數字
[:alpha:] 代表任何英文大小寫字元,亦即 A-Z, a-z
[:lower:] 小寫字母,示例:[[:lower:]],相當於[a-z]
[:upper:] 大寫字母
[:blank:] 空白字元(空格和製表符)
[:space:] 包括空格、製表符(水平和垂直)、換行符、回車符等各種型別的空白,比[:blank:]包含的範圍廣
[:cntrl:] 不可列印的控制字元
[:digit:] 十進位制數字
[:xdigit:]十六進位制數字
[:graph:] 可列印的非空白字元
[:print:] 可列印字元
[:punct:] 標點符號
範例:
[root@localhost meng]# cat file8.txt 
1
3
9
apple
pear
dog
158


# [] 匹配包含括號內的任意字元
[root@localhost meng]# grep '[d]' file8.txt 
dog

# [^]除了括號內的字元
[root@localhost meng]# grep '[^dog]' file8.txt 
1
3
9
apple
pear
158


# 匹配範圍內的字元
[root@localhost meng]# grep '[1-6]' file8.txt 
1
3
158

# 匹配包含字母的字元
[root@localhost meng]# grep '[[:alpha:]]' file8.txt 
apple
pear
dog

匹配次數

* #匹配前面的字元任意次,包括0次
.* #任意長度的任意字元
\? #匹配其前面的字元出現0次或1次
\+ #匹配其前面的字元出現最少1次
\{n\} #匹配前面的字元n次
\{m,n\} #匹配前面的字元至少m次,至多n次
\{,n\}  #匹配前面的字元至多n次,<=n
\{n,\}  #匹配前面的字元至少n次

範例:
#匹配匹配前面的字元任意次,包括0次
[root@localhost meng]# grep 'a*' file8.txt 
1
3
9
apple
pear
dog
158

#匹配其前面的字元出現0次或1次
[root@localhost meng]# grep 'a\?' file8.txt 
1
3
9
apple
pear
dog
158
[root@localhost meng]# grep 'dog\?' file8.txt 
dog

#匹配前面的字元n次
[root@localhost meng]# grep 'p\{2\}' file8.txt 
apple

\{n,\}  #匹配前面的字元至少n次
[root@localhost meng]# grep 'p\{2,\}' file8.txt 
apple

位置錨定

^:匹配行首。
$:匹配行尾。
^[[:space:]]*$:空白行
\<PATTERN\>:匹配整個單詞

範例:
[root@localhost meng]# cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Sun Oct 20 19:35:58 2024
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=982d5922-9968-45a9-9859-6ef07c69a7ec /boot                   xfs     defaults        0 0
/dev/mapper/rl-swap     none                    swap    defaults        0 0

# 除了以#開頭的任意字元
[root@localhost meng]# grep '^[^#]' /etc/fstab
/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=982d5922-9968-45a9-9859-6ef07c69a7ec /boot                   xfs     defaults        0 0
/dev/mapper/rl-swap     none                    swap    defaults        0 0

#匹配整個單詞
[root@localhost meng]# grep '\<swap\>' /etc/fstab
/dev/mapper/rl-swap     none                    swap    defaults        0 0

分組

\( \):分組,用於捕獲子表示式
\1:引用第一個捕獲組
\2:引用第二個捕獲組,依此類推

範例:
# 匹配包含 ap 的行
[root@localhost meng]# grep 'ap' file8.txt 
apple

# 匹配包含 a 後跟任意字元再跟 a 的行
[root@localhost meng]# grep 'a.\(a\)' file8.txt 
banana

基本正則(BRE)和擴充套件正則(ERE)的區別

區別一:
BRE: +、?、{、}、|,使用這些字元時需要轉義(\),如\?, \+
ERE:不需要轉義,可直接使用

區別二:
BRE分組時,使用的是\(\),例:\(abc\)
ERE分組時,使用的是(),例:(abc)

例項

[root@localhost meng]# cat file1.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

#BRE 刪除每行的第一個字元
[root@localhost meng]# sed 's/^.//' file1.txt 
oot:x:0:0:root:/root:/bin/bash
in:x:1:1:bin:/bin:/sbin/nologin
aemon:x:2:2:daemon:/sbin:/sbin/nologin
dm:x:3:4:adm:/var/adm:/sbin/nologin

解讀:s:替換 , /^.: ^是行首,.匹配任意字元(/是轉義), //:空字串

# 刪除每行的第二個字元
[root@localhost meng]# cut -c1,3- file1.txt | paste -sd '\n'
rot:x:0:0:root:/root:/bin/bash
bn:x:1:1:bin:/bin:/sbin/nologin
demon:x:2:2:daemon:/sbin:/sbin/nologin
am:x:3:4:adm:/var/adm:/sbin/nologin

解讀:-c1,3-:提取第一個字元和第三個字元及以後的部分
     paste -sd '\n':將提取的結果重新組合成行

#BRE 刪除每行最後一個字元
[root@localhost meng]# awk '{ sub(/.$/, ""); print }' file1.txt 
root:x:0:0:root:/root:/bin/bas
bin:x:1:1:bin:/bin:/sbin/nologi
daemon:x:2:2:daemon:/sbin:/sbin/nologi
adm:x:3:4:adm:/var/adm:/sbin/nologi

解讀: sub(/.$/, ""); print 是一個awk指令碼, 
sub:在 awk 中用於查詢並替換第一個匹配的子字串
格式:sub(regex, replacement, target)
regex代表正規表示式
replacement代表用於替換匹配到的子字串
target代表當前行
即:
sub(/.$/, ""); print :將最後一個字元替換為 ""(空)。
/.$/:正規表示式,匹配 最後一個字元。
"":替換為 空。
print:列印處理後的字串

# 刪除每一行倒數第二個字元
[root@localhost meng]# rev file1.txt | cut -c1,3- | rev
root:x:0:0:root:/root:/bin/bah
bin:x:1:1:bin:/bin:/sbin/nologn
daemon:x:2:2:daemon:/sbin:/sbin/nologn
adm:x:3:4:adm:/var/adm:/sbin/nologn

解讀: rev是將內容逆向顯示,第一個rev將內容逆向,然後執行cut,第二個rev再把內容逆回來

shell指令碼之變數

變數命名規則
名稱規則:

  • 變數名只能包含字母(a-z, A-Z)、數字(0-9)和下劃線(_)。
  • 變數名不能以數字開頭。
  • 變數名區分大小寫。

賦值規則:

  • 變數賦值時,等號兩邊不能有空格。
  • 變數引用時,使用 $ 符號加上變數名。

變數型別

普通變數:
生效範圍為當前shell程序;一旦關閉終端或指令碼執行結束就會銷燬。對當前shell之外的其它shell程序,包括當前shell的子shell程序均無效。

環境變數:
生效範圍為當前shell程序及其子程序;可以使子程序(包括孫子程序)繼承父程序的變數,但是無法讓父程序使用子程序的變數。

name=VALUE   #賦值變數(普通變數)
export name  #宣告變數(環境變數)

$name        #用於在命令中使用變數的值
echo $name   #將變數的值輸出到終端或檔案,常用於除錯和顯示資訊
unset name   #刪除變數

echo $BASHPID  #檢視shell程序的pid
cat /proc/$PID/environ  #檢視程序的環境變數

只讀變數:
使用 readonly 命令將變數設定為只讀,一旦設定為只讀,變數的值不能被修改。

[root@localhost meng]# readonly num=100
[root@localhost meng]# echo $num
100
[root@localhost meng]# num=99
-bash: num: 只讀變數

位置變數:
表示傳遞給指令碼或函式的引數,透過 $1, $2, $3 等引用。

[root@localhost meng]# cat shell1.sh 
#!/bin/bash
echo "hello world"
echo "first word: $1"
echo "second word: $2"
[root@localhost meng]# bash shell1.sh yes no
hello world
first word: yes
second word: no

狀態變數
表示當前的狀態或資訊。

常見特殊變數:
$?:上一個命令的退出狀態碼(常用於檢驗上一個命令是否成功,返回值為0代表成功)
$$:當前 Shell 程序的 PID
$!:最近一個後臺程序的 PID
$#:傳遞給指令碼或函式的引數個數
$*:所有位置引數作為一個字串
$@:所有位置引數,每個引數作為一個單獨的字串

[root@localhost meng]# cat file1.txt > /dev/null
[root@localhost meng]# echo $?
0
[root@localhost meng]# echo $$
1500

使用shell解決雞兔同籠問題

30雞和兔的頭,80雞和兔的腳,分別有幾隻雞,幾隻兔?

#!/bin/bash
# 定義變數
heads=30
feet=80

#雞的數量
chicken=$(( (4 * heads - feet) / 2 ))

#兔的數量
rabbit=$(( heads - chicken ))

echo "雞:$chicken"
echo "兔:$rabbit"

[root@localhost meng]# bash shell2.sh 
雞:20
兔:10
                 

結合shell完成迴圈和條件判斷


#!/bin/bash

#遍歷 21-30 的數字
for a in {21..30}

# 使用do-while迴圈判斷使用者是否存在

do
   #將迴圈變數a依次附加到user後面,形成使用者名稱user1,user2.。
    Username="User$a"

   # &>/dev/null 減少不必要的輸出
    if id "$Username" &>/dev/null; then
        echo "使用者 $Username 已存在"
    else
        useradd "$Username"
    # 判斷useradd命令是否成功
        if [ $? -eq 0 ]; then
            echo "使用者建立成功"
         else
            echo "使用者已建立"
         fi
      fi
done



相關文章