Shell之三劍客命令(grep sed awk)
阿新 • • 發佈:2021-02-05
技術標籤:Shell入門到入墳shell正則表示式linux
文章目錄
1. grep
1. grep介紹
主要用於過濾文字,還支援 管道符(|)
注:不是所有命令都支援放倒管道符後面的。用xargs讓不支援的也也支援管道 例:find … | xargs -I {} -rm -rf {}
2. 基本用法
1. grep使用
grep 選項 ‘命令’ 檔案路徑
注:“命令” 跟 ‘命令’ 一樣
2. grep選項
# -n 顯示行號
grep -n 'root' /etc/passwd
# -o 只顯示過濾成功的內容
grep -n 'root' /etc/passwd # 只輸出一堆 root
# -i 忽略大小寫
# -A n 匹配成功的當前行 及其後n行
# -B n 為前兩行
# -C n 前後兩行
grep -A 2 'root' /etc/passwd
# -c 顯示出有幾行匹配成功
# -v 取反
ps aux | grep ssh |grep -v grep
# -w 只過濾單詞 (連續的字母數字下劃線組成的)
grep -w "xiao" a.txt
# -r 遞迴的過濾
# -l 顯示匹配成功的檔案
grep -rl "root" /etc/ # 將etc檔案下的全部子檔案子子檔案有root過濾出來
# grep -E 等同於 egrep 擴充套件正則表示式
# --color=auto 顏色 預設就有
# 可以輸入 alias grep 檢視
3. 普通的正則表示式
# ^ 以root開頭
grep "^root" /etc/passwd
# $ 以root結尾
grep "root$" /etc/passwd
# . 任意一個字元
grep "roo." /etc/passwd
# * 左邊的字元出現0 次 或者無窮次 預設貪婪 a.*b 吃到遠的b
# 如果想非貪婪 需要 grep -P '.*?' -P表示支援perl的正則
grep "ab*" a.txt # 必須有a b沒有也行 無數個也行
# [ ] 匹配單個字元 [0-9a-z] 範圍 想匹配 - 則需要放到最左或最右
# [^0-9 ] 取反
grep 'a[1x]b' a.txt # 只對應出 a1b 跟axb
# 用 < > 或 -w 界定單詞邊界
grep \<22\> grep -w "22"
# -Pz P表示啟用perl正則表示式 z表示多行處理
使 \n \t 等有效
4. 擴充套件正則表示式 (egerp)
# * 可以沒有也可以多個
# + 1次或者無窮次
# ? 0次或者1次
# {}自己規定次數
ab{0,} 等同於 ab*
ab{1,} 等同於 ab+
ab{0,1} 等同於 ab?
# ( ) 一個括號一個分組 ()() \1 \2
egrep "(xiao)12\1" # 等同於 "xiao12xiao"
# | 左右兩個正則表示式 表示或者關係
“root|haha”
2. sed
1. sed介紹
sed全稱(stream editor)流式編輯器,sed主要用來自動編輯一個或多個檔案,簡化對檔案的反覆操作,編寫裝換程式等
原理: sed程序會申請一段記憶體,將其劃分為兩部分模式空間 與 保持空間,操作檔案時 一行行讀入模式空間,一行行操作後,預設一行行流出到螢幕上。
注:sed不能用$?判斷成功與否,因為退出狀態一直為0 ,只有存在語法錯誤時,sed的退出狀態才不是0
2. 基本用法
1. sed的使用
sed 選項 ‘定位+命令’ 檔案路徑
2. sed的選項
選項 | 功能 |
---|---|
-r | 支援正則表示式(一般都寫) |
-i | 輸出到螢幕的內容輸入到檔案內(預設輸出到螢幕) |
-n | 取消預設輸出 |
-e(‘3d;3p’) | 多段規則(sed -e ‘3d’ -e ‘3d’) |
-f | 從檔案讀取規則(sed -f -a.sed a.txt) |
3. sed定位
1.行號定位:
# 第一行刪除
sed -r '1d' a.txt
# 1-5行刪除 範圍定位
sed -r '1,5d' a.txt
# 1 3 6 行刪除
sed -r '1d;3d;6d' a.txt
# 第一行到最後一行刪除
sed -r '1,$d' a.txt
2.正則定位:
# 刪除 包含xiao
sed -r '/xiao/d' a.txt
# 刪除 以xiao結尾
sed -r '/xiao$/d' a.txt
# 刪除 以xiao開頭
sed -r '/^xiao/d' a.txt
# 刪除xiao開頭 xiao結尾 中間任意
sed -r '/^xiao.*xiao$/d' a.txt
注: 正則表示式 包含在 \c 正則 c ,c可以是任何字元 用 // 時 前面不需要帶反斜槓(\),當正則包含 路徑時, 可以用 @ (#)包含
3.範圍定位
# 1-5行刪除 範圍定位
sed -r '1,5d' a.txt
# 從第3行開始 到最近匹配成功的 (n結尾)的正則為止 (非貪婪)
sed -r '3,/n$/d' a.txt
4. 命令
命令 | 功能 |
---|---|
a(i) | 追加到下一行(插入到上一行) |
c | 修改 例: sed -r '3c xxxxxx ’ a.txt |
d | 刪除 |
s/xxx/yyy/g | 將xxx換為yyy(xxx與yyy可以正則操作) |
& | 取正則匹配的原內容 ( s/[0-9]$/&xiao/g)效果為最後一個位數字的行 新增上xiao |
e | 多重編輯 |
i | 忽略大小寫 |
! | 取反 例: ‘1,8!d’ 即1-8行以外的刪除 |
r | 讀取檔案到目標行 例: sed -r ‘4r 1.conf’ a.txt |
w | 寫入其他檔案 |
y | 對應替換 例: ‘y/ab/XY/’ 所有a->X b->Y |
q | 退出 3q 第三行退出,後續不輸出 |
5. 模式空間 與 保持空間
命令 | 功能 |
---|---|
x | 交換模式空間與保持空間 |
h | 模式空間複製/覆蓋 保持空間 |
H | 模式空間追加到保持空間 |
g | 保持空間複製/覆蓋到模式空間 |
G | 保持空間追加到模式空間 |
n | 讀取下一行到 /覆蓋 到模式空間 |
N | 將下一行新增到模式空間 |
d | 刪除預設輸出 |
瞭解即可:
例子:
檔案a.txt內容為
111
222
333
修改為
333
222
111
方式一:
sed -r '1h;1d;2G;2h;2d;3G' a.txt
方式二:
tac a.txt
3. awk
1. awk介紹
awk本身就是一門程式語言,awk命名由來為他的三個作者的首字母
2. 基本用法
1. awk的使用
awk 選項 ‘BEGIN{}模式匹配{}END{}’ 檔案路徑 (也支援放到管道後方)
head -10 /etc/passwd | awk -F: 'BEGIN{count=0}{print $0;count++}END{print count}'
1. 最先執行:行前處理程式碼 BEGIN{count=0}
FS 指定輸入分割符 'BEGIN{count=0;FS=":"}' 效果等同 -F:
OFS 指定輸出分隔符 'BEGIN{count=0;FS=":";OFS="-"}' 原來逗號(,)效果為空格 現在改為 - 號
2. 再執行:行處理
(1)
-F: 效果 以:為界切分成n段 為$1-$n
$0 為整行
NR 行號
NF 段數
(2)
執行行處理程式碼:{print $0;count++}
(3)
迴圈,直到所有行處理完畢
3. 最後執行: 行後處理
END{print count}
從檔案中讀取規則則 :awk -F: -f 1.awk /etc/passwd
2. 模式匹配
行定位
# awk -F: 'NR == 3{print NR,$1}' /etc/passwd
NR == 3 第三行
NR >=1 && NR<=3
NR == 1 ||NR == 2
正則定位
# awk -F: '/^root/{print NR,$1}' /etc/passwd
^root root開頭
部段正則匹配
# awk -F: '$1 ~ /root/{print NR,$1}' /etc/passwd
輸出 第一段中 包含root的行
範圍匹配 大於等於3 小於等於7 且包含root的行
awk 'NR >= 3 && NR <=7 && /root/{print NR,$0}' /etc/passwd
# !()的使用 取反
awk -F: '!($1 ~ /root/){print NR,$1}' /etc/passwd
awk -F: '$1 !~ /root/{print NR,$1}' /etc/passwd
3. 格式化輸出(print -> printf)
awk -F: '{printf "行號:%s---使用者名稱:%s\n",NR,$1}' /etc/passwd
4. 流程控制
awk -F: 'BEGIN{X=0;y=0;z=0}{if ($3 == 0 ){x++} else if ( $3>1 && $3<=999){y++} else {z++}}END{printf "管理員:%s\n系統使用者:%s\n 普通使用者數:%s\n",x,y,z}' /etc/passwd
shell寫法改寫:
#!/bin/bahs
x=0
y=0
z=0
for uid in $(awk -F: '{print $3}' /etc/passwd)
do
if [ $uid -eq 0 ];then
let x++
elif [ $uid -ge 1 -a $uid -le 999 ];then
let y++
else
let z++
fi
done
printf "管理員:%s\n系統使用者:%s\n 普通使用者數:%s\n" $x $y $z
5. 流程控制
awk '{n=0;while (n<3){print $0,n++}}' a.txt
awk '{for (n=0;n<3;n++){print $0}}' a.txt
6. 陣列
emmmm 累了 用到在學把