Shell程序设计 | 文本处理工具 :正则表达式、grep、sed、awk
文章目錄
- 正則表達式
- grep
- sed
- awk
- 其它常用工具
- cut
- sort
- uniq
- tr
- 常見面試題
- 第十行
- 有效電話號碼
- 統計詞頻
- 轉置文件
要想使用這些流式處理工具,那么就必須得了解正則表達式,由于正則表達式內容較多,一篇博客肯定寫不完,所以這里只是簡單的講一下正則表達式的常用語法。
正則表達式
元字符
| \ | 轉義字符 |
| . | 匹配任意一個字符 |
| * | 匹配其前面的字符0次或者n次 |
| ^ | 匹配開頭 |
| $ | 匹配結尾 |
| [a-z] | 匹配方括號中的任意一個字符 |
拓展元字符
| + | 匹配前面的正則表達式至少一次 |
| ? | 匹配前面的正則表達式,出現0次或者一次 |
將這些元字符搭配起來,就成為了正則表達式,在下面幾個工具的用例中會進行具體演示
下面介紹Linux中流式文本處理的三劍客——文本過濾工具grep、文本編輯工具sed、文本報告生成器awk
grep
grep是一種強大的文本搜索工具,它能使用正則表達式搜索文本,并把匹配的行打印出來。它也是我們在linux中最常用到的工具之一
語法
grep [選項](查詢內容)(參數)常用選項
-i:忽略大小寫 -r:遞歸讀取一個目錄下所有文件 -E:支持拓展正則表達式sed
sed是一種強大的文本編輯工具。它一次處理一行內容,處理時把當前處理行存儲在臨時緩沖區中(模式空間)中,接著使用sed命令處理緩沖區中的內容,把處理完的數據送往終端,接著輸出下一行數據,直至文件末尾
語法
sed [選項] '命令' (參數)常用選項
-e:直接在指令列模式上進行sed的動作編輯,即可以使用多次命令 -n:只輸出匹配行(也可以指定修改行) -r:支持使用擴展正則表達式常用命令
a:追加,在下一行出現 i:插入,在上一行出現 d:刪除 s:查找并替換 p:打印當前模式空間內容使用示范,以下列文本分別進行增刪改
hello world this is test file aaaaa bbbbbbb cccccccccc 123123124 world hello在以t開頭的行的下一行追加xxxxxxxxx
cat test3 | sed '/^t/axxxxxxxxx'
刪除所有以d結尾的行
將文本中的所有b替換為d
awk
awk一個強大的文本分析工具,把文件逐行的讀入,以空格為默認分隔符將每行切片,切開的部分再進行分析處理。
其實awk是是一門用于處理文本文件的編程語言,而gawk是這門編程語言的具體實現,因此其支持和shell類似的算術運算、條件判斷、流程控制等語法。
下面是man手冊中awk的說明,當我們查詢awk的時候就會自動跳轉至gawk
語法
awk [選項] ‘匹配模式1{執行操作1} 匹配模式2{執行操作2}......’ (參數)注意:只有匹配了pattern的行才會執行action
同時也可以指定開頭和結尾執行的內容
awk [選項] ‘BEGIN{開始時執行的內容} 匹配模式1{執行操作1} END{結束時執行的內容}’ (參數)注意:BEGIN 在所有數據讀取行之前執行;END 在所有數據執行之后執行。
常用選項
-F<分隔字符>:指定輸入文件折分隔符 -v:賦值一個用戶定義變量常用系統變量
FILENAME:文件名 NR:已讀的記錄數(即當前的行數) NF:瀏覽記錄的域的個數(切割后,列的個數)由于awk數組、運算、條件判斷、流程控制、函數等內容與shell和c語言高度類似,這里就不多花篇幅介紹了
使用示范:切割出ifconfig中ens38的ip地址
ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.220.128 netmask 255.255.255.0 broadcast 192.168.220.255inet6 fe80::8e00:5dc0:711b:a9cf prefixlen 64 scopeid 0x20<link>ether 00:0c:29:4e:dd:e4 txqueuelen 1000 (Ethernet)RX packets 1513042 bytes 952654297 (908.5 MiB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 1444185 bytes 1229233776 (1.1 GiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0inet6 ::1 prefixlen 128 scopeid 0x10<host>loop txqueuelen 1000 (Local Loopback)RX packets 185821127 bytes 25600956325 (23.8 GiB)RX errors 0 dropped 5322 overruns 0 frame 0TX packets 185821127 bytes 25600956325 (23.8 GiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ifconfig ens38 | grep inet\ | awk -F " " '{print$2}'
使用示范:查找出文本中的空行
其它常用工具
以下是其他常用的工具,由于用法簡單,所以這里就簡單介紹一下
cut
cut的主要功能就是剪切數據
語法
cut [選項](參數)常用選項
-f:列號,提取第幾列 -d<分隔字符>:分隔符,按照指定分隔符分割列使用示范:獲取文本中的姓名
name age alice 21 ryan 30 cat test | cut -d ' ' -f 1sort
sort用于對文本內容進行排序
語法
sort [選項](參數)常用選項
-t<分隔字符>:指定排序時所用的欄位分隔字符 -n:依照數值的大小排序 -r:以相反的順序來排序 -k:指定需要排序的列使用示范:對文本中的數據進行排序
123123 42 647 453 6789 23 1 457 97312 cat nums | sort -nuniq
uniq命令用于對數據流進行去重,通常與sort搭配使用
語法
uniq [選項](參數)常用參數
-c:在每列旁邊顯示該行重復出現的次數; -d:僅顯示重復出現的行列;使用示范:統計文本中每個單詞出現的次數
the day is sunny the the the sunny is is先去重,根據重復的次數進行排序
cat test2 | uniq -c | sort -ntr
tr用于對文本內容進行修改、替換、壓縮
語法
tr [選項](參數)常用參數
-d:刪除所有屬于第一字符集的字符; -s:把連續重復的字符以單獨一個字符表示使用示范:將小寫轉換為大寫
the day is sunny the the the sunny is is cat words | tr 'a-z' 'A-Z'常見面試題
以下題目來源于leetcode
第十行
leetcode-195. 第十行
給定一個文本文件 file.txt,請只打印這個文件中的第十行。
示例:
假設 file.txt 有如下內容:
你的腳本應當顯示第十行:
Line 10說明:
答案:
解法1:sed -n '10p' file.txt 解法2:awk 'NR==10{print $0}' file.txt 解法3:tail -n +10 file.txt | head -n 1解題思路:
有效電話號碼
leetcode-193. 有效電話號碼
給定一個包含電話號碼列表(一行一個電話號碼)的文本文件 file.txt,寫一個 bash 腳本輸出所有有效的電話號碼。
你可以假設一個有效的電話號碼必須滿足以下兩種格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一個數字)
你也可以假設每行前后沒有多余的空格字符。
示例:
假設 file.txt 內容如下:
你的腳本應當輸出下列有效的電話號碼:
987-123-4567 (123) 456-7890答案:
awk '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$/' file.txt解題思路:
統計詞頻
leetcode-192. 統計詞頻
寫一個 bash 腳本以統計一個文本文件 words.txt 中每個單詞出現的頻率。
為了簡單起見,你可以假設:
words.txt只包括小寫字母和 ’ ’ 。
每個單詞只由小寫字母組成。
單詞間由一個或多個空格字符分隔
示例:
the day is sunny the the the sunny is is你的腳本應當輸出(以詞頻降序排列):
the 4 is 3 sunny 2 day 1答案:
cat words.txt | tr -s ' ' '\n' | sort | uniq -c | sort -nr | awk '{print $2,$1}'解題思路:
轉置文件
leetcode-194. 轉置文件
給定一個文件 file.txt,轉置它的內容。
你可以假設每行列數相同,并且每個字段由 ’ ’ 分隔.
示例:
假設 file.txt 文件內容如下:
應當輸出:
name alice ryan age 21 30答案:
awk '{for (i=1; i<=NF; i++){if (NR==1) {res[i]=$i}else{res[i]=res[i]" "$i}} } END{ for(j=1; j<=NF; j++){print res[j]} }' file.txt解題思路:
總結
以上是生活随笔為你收集整理的Shell程序设计 | 文本处理工具 :正则表达式、grep、sed、awk的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Shell程序设计 | 基本语法 :变量
- 下一篇: 高级数据结构与算法 | LFU缓存机制(