字符截取命令
一、cut命令
功能:用于從文件或標準輸入中提取指定字段或列
語法:cut [選項] 文件名
- -f:列號,提取第幾列,默認識別制表符分割出來的列(列號之間用,隔開)
- -d:分隔符,按照指定的分隔符進行分割,然后結合-f提取指定列
- -c:字符范圍,不依賴分隔符,通過字符范圍進行提取(n-m:從第n個提取到第m個字符;n-:從第n個字符開始提取到結尾;-m:從第1個字符提取到第m個字符)
1.準備測試數據
[root@localhost ~]# cat cut.txt
ID NAME LINUX MYSQL DOCKER
0 xzhao 95 59 78
1 xqian 83 75 93
2 xsun 74 96 632.用-f選項過濾指定列的內容
[root@localhost ~]# cut -f 2,5 cut.txt
NAME DOCKER
xzhao 78
xqian 93
xsun 63
#cut只能分割用制表符分開列的文件,若列是用其他符號分割的,需要用-d選項指定3.通過-d指定分隔符的方式過濾指定文件的第7列
[root@localhost ~]# cut -d: -f 7 /etc/passwd
/bin/bash
/sbin/nologin4.獲取當前所在路徑的最后一個層級目錄
[root@localhost ~]# pwd
/root
[root@localhost ~]# pwd | cut -d/ -f 2
root#-c 可以按照字符數量進行截取,按照對應格式可以取到對應位置的字符
#截取多個范圍的字符時用,隔開
5.用-c選項截取指定范圍的列
[root@localhost ~]# head -n 5 anaconda-ks.cfg
# Generated by Anaconda 34.25.4.9
# Generated by pykickstart v3.32
#version=RHEL9
# Use graphical install
graphical
[root@localhost ~]# head -n 5 anaconda-ks.cfg | cut -c 1-5
# Gen
# Gen
#vers
# Use
graph
二、awk命令
功能:對文件進行行提取和列提取
格式:awk ‘條件{動作}’ 文件名
- 條件的作用:通過指定條件過濾出符合條件的行,沒有指定則是操作所有行
- 動作的作用:通過動作將符合條件的行打印出來,打印時可選擇打印該行中的哪些列
注:條件控制行,動作控制列
例:awk? '{print 列}'? 文件名? 或? awk? '{printf 列}'? 文件名——(不換行)
- awk的內置參數$n:n=0表示所有列,n=1表示第一列......
- 從printf打印輸出可以看出,awk的工作原理是一行一行去處理的
- NF:這行的列數(固定);$NF可以去每列的最后一行;$(NF-1)可以取倒數第二列
- FS:用來聲明awk的分隔符,如BEGIN{FS=":"};或-F指定分隔符
- NR:當前行(變化),即awk 'NR==2{print $2"\t"$4}' 文件名
#不指定任何條件,直接執行動作,并選擇輸出哪些列,常用printf來打印
1.等價cut,截取第2列和第5列的值
[root@localhost ~]# awk '{print $2"\t"$5}' cut.txt
NAME DOCKER
xzhao 78
xqian 93
xsun 632.讀取文件中任意一列的數據
[root@localhost ~]# awk '{printf $1"\t" $2"\t" $3"\n"}' cut.txt
ID NAME LINUX
0 xzhao 95
1 xqian 83
2 xsun 74
[root@localhost ~]# awk '{printf $0 "\n"}' cut.txt
ID NAME LINUX MYSQL DOCKER
0 xzhao 95 59 78
1 xqian 83 75 93
2 xsun 74 96 63#NF
3.讀取文件每行的總列數
[root@localhost ~]# awk '{print NF}' cut.txt
5
5
5
5
4.獲取文件的最后一列
[root@localhost ~]# awk '{print $NF}' cut.txt
DOCKER
78
93
63
5.獲取文件的倒數第二列
[root@localhost ~]# awk '{print $(NF-1)}' cut.txt
MYSQL
59
75
96
6.獲取文件的第一列和最后一列
[root@localhost ~]# awk '{print $1"\t"$NF}' cut.txt
ID DOCKER
0 78
1 93
2 63#FS或-F,FS條件直接使用沒有辦法正常匹配第一行,需要用到BEGIN;默認分隔符是空白
7.讀取/etc/passwd的第一列和最后一列
[root@localhost ~]# awk '{FS=":"}{print $1 "\t" $NF}' /etc/passwd
root:x:0:0:root:/root:/bin/bash root:x:0:0:root:/root:/bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
.....................
[root@localhost ~]# awk -F: '{print $1 "\t" $NF}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
.....................
[root@localhost ~]# awk 'BEGIN{FS=":"}{print $1 "\t" $NF}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin#NR條件
8.截取磁盤的使用率
[root@localhost ~]# df -h | awk '{print $5}'
已用%
0%
0%
2%
12%
13%
0%
9.截取磁盤的使用率的數據部分
[root@localhost ~]# df -h | awk 'NR>1{print $5}'
0%
0%
2%
12%
13%
0%
10.截取根分區的磁盤使用率
[root@localhost ~]# df -h | awk 'NR==5{print $5}'
12%
11.截取根分區磁盤使用率的數字部分
[root@localhost ~]# df -h | awk 'NR==5{print $5}' | cut -d% -f1
12
三、awk的條件
1.自定義條件
- 關系運算條件(>,<,>=,<=,==,!=):用來判斷左右兩側的關系
- 包含匹配條件(~,!~,~//,!~//):用來進行匹配包含關系的,支持正則
1.列出所有行號大于1的行的列數據
[root@localhost ~]# awk 'NR>1{print $0}' cut.txt
0 xzhao 95 59 78
1 xqian 83 75 93
2 xsun 74 96 632.列出學號為2的各科成績單
[root@localhost ~]# awk '$1==2{print $0}' cut.txt
2 xsun 74 96 633.列出LINUX成績大于等于80的成績單
[root@localhost ~]# awk '$3>=80{print $2"\t"$3}' cut.txt
NAME LINUX
xzhao 95
xqian 834.獲取當前用戶使用的網卡名
[root@localhost ~]# ip add | grep "inet[^6]" | grep -v "127" | awk '{print $NF}'
ens1605.列出第二列包含字符q的數據
[root@localhost ~]# awk '$2~"q"{print $0}' cut.txt
1 xqian 83 75 936.列出第二列以字符n結尾的數據
[root@localhost ~]# awk '$2~"n$"{print $0}' cut.txt
1 xqian 83 75 93
2 xsun 74 96 637.列出包含數字3的數據
[root@localhost ~]# awk '$0~"3"{print $0}' cut.txt
1 xqian 83 75 93
2 xsun 74 96 63
或
[root@localhost ~]# awk '$0~/3/{print $0}' cut.txt
或
[root@localhost ~]# awk '/3/{print $0}' cut.txt 8.列出以.com結尾的數據
[root@localhost ~]# awk '/\.com$/{print $0}' cut.txt
2.預定義條件
- BEGIN:在awk未讀取數據前聲明的條件
- END:在awk處理完所有數據后聲明的條件
[root@localhost ~]# awk 'BEGIN{printf "MYSQL成績單:\n"} {printf $2"\t"$4"\n"}' cut.txt
MYSQL成績單:
NAME MYSQL
xzhao 59
xqian 75
xsun 96[root@localhost ~]# awk '{printf $2"\t"$5"\n"}END{printf "以上顯示的是所有人的DOCKER成績\n"}' cut.txt
NAME DOCKER
xzhao 78
xqian 93
xsun 63
以上顯示的是所有人的DOCKER成績
注:
- 若有多個條件(動作),可以用空格分隔
- 在包含匹配中,若想使用特殊字符的轉義態,需要使用~//符號,不能直接用“”
- 可以用“”的地方一定可以用//,但可以用//的地方不一定可以用“”
- awk在使用的時候可能會存在一些格式上的問題
- awk {print $3+$4},還可以做運算
四、動作(printf)
功能:printf是標準的格式化輸出,取消所有默認格式,然后手動指定輸出內容的類型和輸出時的格式
格式:printf? '類型/格式'? 字符串
輸出類型
- %s:將內容按照字符串類型輸出(如:ns代表輸出寬度是n,默認右對齊,-ns是左對齊)
- %i:將內容按照整數類型輸出(如:ni代表輸出的寬度是n,默認右對齊,-ns是左對齊)
- %f:將內容按浮點數類型輸出(如%.2f,保留兩位小數,四舍五入)
輸出格式
- \t:字符之間用制表符分割,即tab鍵
- \n:字符之間用換行符分割,即enter鍵
- 注:輸出格式需要加雙引號
1.使用printf輸出表格文件
[root@localhost ~]# printf %s $(cat cut.txt)
IDNAMELINUXMYSQLDOCKER0xzhao9559781xqian8375932xsun749663[root@localhost ~]#
#在使用printf輸出時,如果僅指定輸出類型,而不指定輸出格式,則會把所有要輸出內容連在一起輸出,變
為一整行[root@localhost ~]# printf '%s\t%s\t%s\t%s\t%s\n' $(cat cut.txt)
ID NAME LINUX MYSQL DOCKER
0 xzhao 95 59 78
1 xqian 83 75 93
2 xsun 74 96 632.在輸出時,想讓第1列使用整數類型輸出,3,4,5列使用浮點類型輸出
[root@localhost ~]# printf '%i\t%s\t%.2f\t%.2f\t%.2f\n' $(cat cut.txt|grep -v ID)
0 xzhao 95.00 59.00 78.00
1 xqian 83.00 75.00 93.00
2 xsun 74.00 96.00 63.003.打印名字和Linux成績,且成績保留2位小數
[root@localhost ~]# printf '%s\t%.2f\n' $(awk 'NR>1{printf $2"\t"$3"\n"}' cut.txt)
xzhao 95.00
xqian 83.00
xsun 74.004.計算每個人的平均值
[root@localhost ~]# awk 'NR>1{printf $2"的平均分是\t"($3+$4+$5)/3"\n"}' cut.txt
xzhao的平均分是 77.3333
xqian的平均分是 83.6667
xsun的平均分是 77.6667
#awk中默認支持數值運算,并且整數、浮點數運算都支持
字符截取命令練習
問題1:監控當前根分區的使用情況(若根分區使用率超過10%,打印紅色超標)
[root@localhost ~]# cat jiance.sh
#!/bin/bash
usage=$(df -h | awk '$NF~/\/$/{print $(NF-1)}' | cut -d% -f1)
[ $usage -gt 10 ] && echo -e "\e[31m 超標 \e[0m"
[root@localhost ~]# bash jiance.sh 超標
[root@localhost ~]#
問題2:列出第二列包含x的行的第2列和第4列(cut.txt)
[root@localhost ~]# cat cut.txt
ID NAME LINUX MYSQL DOCKER
0 xzhao 95 59 78
1 xqian 83 75 93
2 xsun 74 96 63
[root@localhost ~]# awk '$2~"x"{print $2"\t"$4}' cut.txt
xzhao 59
xqian 75
xsun 96
或
[root@localhost ~]# awk '$2~/x/{print $2"\t"$4}' cut.txt
問題3:提取IP地址的網段(ip add)
[root@localhost ~]# ip add | grep "inet[^6]"inet 127.0.0.1/8 scope host loinet 192.168.66.66/24 brd 192.168.66.255 scope global noprefixroute ens160
[root@localhost ~]# ip add | grep "inet[^6]" | grep -v "127"inet 192.168.66.66/24 brd 192.168.66.255 scope global noprefixroute ens160
[root@localhost ~]# ip add | grep "inet[^6]" | grep -v "127" | awk '{print $2}'
192.168.66.66/24
[root@localhost ~]# ip add | grep "inet[^6]" | grep -v "127" | awk '{print $2}' | cut -d. -f3
66
[root@localhost ~]#