Linux15:正則表達式與字符處理


正則表達式與字符處理

正則表達式

正則表達式和通配符的區別是,正則表達式的作用是在文件中搜索符合條件的字符串(常用命令有grep、awk、sed),而通配符用來匹配符合條件的文件名(ls、find、cp這些命令只能用通配符,不能用正則表達式)。且通配符是完全匹配,而正則表達式是包含匹配,如當用grep命令查找時,只要包含該字符串的行就會顯示。

正則表達式:

通配符:

*表示前一個字符匹配0次或任意多次(和通配符中的*不同),故grep "a*" test_rule.txt表示匹配所有內容,包括空白行,而grep "aa*" test_rule.txt表示匹配至少包含有一個a的行。

.表示匹配除了換行符外的任意一個字符,grep "s.*d" test_rule.txt表示匹配在s和d字母之間有任意字符的行,grep ".*" test_rule.txt 表示匹配所有內容。

和$表示能匹配行首和行尾,M表示行首是M,d$表示行尾是d,而grep -n "^$" test_rule.txt 表示會匹配空白行。

常見的匹配:

grep "^[^a-z\]" test_rule.txt 表示匹配不用小寫字母開頭的行

grep "^[^a-zA-Z\]" test_rule.txt 表示匹配不用字母開頭的行

grep "\.$" test_rule.txt 表示匹配使用“.”結尾的行

字符截取命令

截取命令有grep、cut、awk和sed四個。

cut命令

grep是將符合條件的行提取出來,而cut是提取列。

使用的基本格式:cut [選項] 文件名-f后跟列號代表提取第幾列,-d后跟分隔符表示設置提取時的分隔符。對於文件(每行中的分隔符是tab)

ID Name gender Mark
1 Liming M 86
2 Sc M 90
3 Gao M 83

執行cut -f 2,3 student.txt結果就是提取第2、3列(中間分隔符還保留):

Name gender
Liming M
Sc M
Gao M

cut命令會一行一行進行切分,取返回結果中每行第12個字符以后的所有字符串:export | cut -c 12

cut命令常和grep命令配合使用,如對/etc/passwd,該文件中每一行代表一個用戶,如果想提取這個文件中的普通用戶名,應該執行:

cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1

就會將普通用戶名提取出來。這里第一部分代表用cat命令查看該文件,然后選取行內帶/bin/bash的行(相當於除掉系統用戶),然后去除root用戶(-v代表過濾掉某個結果),最后用cut命令提取第一列,分割符是冒號(不設置的話默認分隔符是制表符),中間用管道符連接。

但如果要讀取的文件分隔符是多個空格,則cut無法正確提取內容,cut的分隔符只支持一個字符,awk命令可以解決這個問題。

printf命令

printf的基本用法是printf '輸出格式' 輸出內容

輸出格式主要有三種,%ns表示輸出字符串,n代表輸出字符的個數;%ni代表輸出整數,n指輸出數字的個數;%m.nf表示輸出小數,m指輸出數字的個數,n值其中小數的位數。

輸出格式中有一些特殊字符,常用的有\n換行,\r回車,\t制表符。

printf %s 1 2 3 4 5 6會輸出123456

printf %s %s %s 1 2 3 4 5 6會輸出%s%s123456

必須將輸出格式用單引號括起來:printf '%s %s %s' 1 2 3 4 5 6會輸出1 2 34 5 6

printf '%s %s %s\n' 1 2 3 4 5 6會輸出1 2 3換行4 5 6

也就是說當后面內容多於輸出格式時,會反復使用輸出格式。

想要按照一定的格式輸出文件時,要這樣處理:printf '%s' $(cat student.txt),注意這里不能用管道符,這樣會將文件所有內容在一行輸出,如果想按照文件格式輸出必須按照文件的格式來寫輸出命令:printf '%s\t %s\t %s\t %s\t %s\t %s\t \n' $(cat student.txt)這樣就能完整的輸出文件了student.txt:

ID Name PHP Linux MySQL Average
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Gao 99 83 93 91.66

printf '%10s %5i %8.2f \n' $(cat file),輸出格式依次是長度為10的字符串、長度為5的數字、長度為8其中可以留兩位小數點。

print和printf的區別在於print命令會自動加換行,linux中默認沒有print命令,但在awk中可以使用print命令。

awk命令

awk使用格式:awk ‘條件1{動作1} 條件2{動作2}…’ 文件名條件通常是關系表達式,當使用awk處理文件時,文件是按行讀取的,然后判斷條件,確定是否執行動作。

整個awk的處理流程是:

1、讀取第一行,然后初始化$0/$1/$2...。

2、根據條件值判斷是否進行后面的動作。

3、執行所有的條件和動作,如果后面還有后續的行則重復上述步驟,直到所有行都讀完。

對student.txt來說,awk '{printf $2 "\t" $6 "\n"}' student.txt能將第2列和第6列提取出來,這里的printf不是系統命令,可以用$n代表第幾列,$0代表整行,printf中的特殊字符要用雙引號括起來,因為外層已經使用了單引號,所以這里用雙引號,特殊字符控制的都是輸出格式。

awk默認的字段分隔符是空格或tab,所以對於用多個空格作為分隔符的文件或輸出,awk也能處理,如df -h | awk '{print $1 "\t" $3}'這里用的是print命令,和printf手動加換行符效果相同。

如果想提取df -h中的百分數,如下圖:

此時應該執行df -h | grep root | awk '{printf $5}' | cut -d "%" -f 1這條語句就是用grep命令提取對應行,然后用awk來提取對應列,最后用cut命令來以%為分隔符切割,相當於去掉%,最后得到數字。

BEGIN是一種條件,表示讀取前優先處理。awk 'BEGIN{printf "This is a transcript \n" } {printf $2 "\t" $6 "\n"}' student.txt此時打印內容第一行就是This is a transcript,第二行開始讀取文件。

設置分隔符awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}'FS就代表設置分隔符為冒號,這里前面必須加BEGIN ,如果不加那么文件第一行會原封不動打印,因為在讀取第一個大括號時就已經讀取第一行了,如果不加BEGIN程序會直接讀取第二行然后開始處理。

END也是一種條件,表示最后執行。awk 'END{printf "The End \n" } {printf $2 "\t" $6 "\n"}' student.txt此時就會最后打印一行The End。

awk的強大之處在於可以插入邏輯表達式,cat student.txt | grep -v Name | \ awk '$6 >= 87 {printf $2 "\n" }',同樣是對student文件,如果想輸出平均分大於87分的Name就可以執行這條命令,首先讀取該文件,然后除掉第一行,如果第六列的元素大於等於87就打印第二列。

awk有幾個內建變量:NF(每一行擁有的字段總數)、NR(目前處理的是第幾行的數據)、FS(分隔符默認為空格),這些變量都可以直接放在大括號里打印出來,或者放在括號外作為條件判斷都可以,不需要加$。

sed命令

sed命令是一種輕量級流編輯器,主要是用來將數據選取、替換、刪除和新增。vim也可以修改文件,但是vim難以修改命令輸出內容,只能將輸出內容寫入文件然后修改,而sed在這方面優於vim。

sed命令的執行格式是sed [選項] ‘[動作]’ 文件名

提取文件第2行並輸出:sed -n '2p' student.txt,動作中p代表輸出指定的行,而-n代表僅輸出sed處理過的行,如果不加-n那么會輸出全部文件內容,第二行會輸出兩次。sed不僅可以用在文件中,還能用在命令輸出的內容中:df -h | sed -n '2p'

刪除第2行到第4行的數據(相當於輸出其他行,它不會修改文件本身):sed '2,4d' student.txt

在第二行后插入一行(不修改文件本身):sed '2a hello' student.txt,a代表某行后插入。

在第二行前插入兩行(不修改文件本身):sed '2i hello \ world' student.txt,反斜杠代表輸入第二行,插入時除了最后一行,當想插入多行時必須在行末處加反斜杠,i代表某行前插入。

將第二行替換(不修改文件本身):sed '2c No such person‘ student.txt

數據替換可以精確到字符串,格式是sed ‘s/舊字串/新字串/g’ 文件名

把第三行中的74換成99:sed '3s/74/99/g' student.txt

同時把“Liming”和“Gao”替換為空:sed -e 's/Liming//g ; s/Gao//g' student.txt,注意當有多個動作時用分號隔開,-e代表允許多條編輯,當s前沒有數字時代表針對所有行。

總結:sed命令的常用選項有三個,-n、-e和-i‘;常用動作有6種,a、c、i、d、p、s。

字符處理命令

1、排序命令sort,使用方法:sort [選項] 文件名選項有幾種:

-f: 忽略大小寫
-n: 以數值型進行排序,默認使用字符串型排序
-r: 反向排序
-t: 指定分隔符,默認是分隔符是制表符
-k n[,m]: 按照指定的字段范圍排序。從第n字段開始, m字段結束(默認到行尾)

排序用戶信息文件:sort /etc/passwd此時會輸出按照文件每行首字母排序的結果:

如果想按照每行第三個字段排序,必須先指定冒號為分隔符:sort -t ":" -k 3,3 /etc/passwd

-k 3,3的意思是從第三個字段開始到第三個字段結束,也就是按照第3個字段排序。但是排序結果會把10排在3前,這是因為默認只識別第一個字符,如果想按數字排序應該加上-n選項:

sort -n -t ":" -k 3,3 /etc/passwd

2、去重命令uniq:經常結合排序使用,僅取出賬號欄,然后排序后去重:

last | cut -d ' ' -f 1 | sort | uniq

3、統計命令wc:wc [選項] 文件名。選項有以下幾種:-l: 只統計行數、-w: 只統計單詞數、-m: 只統計字符數。如果不加選項那么上述三種都會輸出。

字符轉換命令

1、tr命令可以用來刪除一段訊息中的文字或進行替換

將last輸出信息中的所有小寫字母換成大寫的:last | tr '[a-z]' '[A-Z]'

將輸出信息中的冒號全部刪除:cat /etc/passwd | tr -d ':'

2、col命令可以將tab轉成對等的空格鍵,命令是col -x

3、join命令用來通過兩個文件數據相同的部分,來把兩個文件的數據整合到一起,如/etc/passwd和/etc/shadow兩個文件每行的第一個字段都是相同的賬號名:

此時就可以用join方法:

join -t ':' /etc/passwd /etc/shadow

這樣整合后,兩個文件的數據都會整合到一起,查看上面輸出的內容:

可以發現最后每一行輸出的內容就是文件1+文件2沒有連接字段的那部分。join的字段也可以不采用首個字段。

join常常在sort之后,防止出現對應行不匹配的現象。

4、paste命令用來將兩行粘在一起,中間用tab鍵分開:paste 文件1 文件2,如果加-d后面跟分隔符的話就可以重新設置分隔符。

5、expand和unexpand分別是將tab轉成空格,和把空格轉成tab,expand后跟文件名會自動將文件內的tab轉成8個空格,也可以用-t加數字來自定義轉換數字。

6、分區命令split,它可以將一個大文件分成多個小文件,以便於復制。

切割成300k一個的小文件:split -b 300k 文件名,此時原文件會被刪除,假設原文件名為1,那么結果就會多出1aa、1ab、1ac文件,將這三個文件合並:cat 1* >> 1,這樣就可以復原。

將ls輸出信息每十行記錄一個文件:ls -al / | split -l 10 - lsroot,這里新生成的文件名開頭就是lsroot,-的意思是輸入流,但是為空所以就用-來表示。

7、xargs命令可以創造標准輸入,令不支持用管道符的命令能夠接受其他命令的返回結果並執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM