日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Shell程序设计 | 文本处理工具 :正则表达式、grep、sed、awk

發布時間:2024/4/11 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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結尾的行

cat test3 | sed '/d$/d'


將文本中的所有b替換為d

cat test3 | sed 's/b/d/g'


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}'


使用示范:查找出文本中的空行

the day is sunny the thethe sunny is is awk '/^$/{print NR}' words


其它常用工具

以下是其他常用的工具,由于用法簡單,所以這里就簡單介紹一下

cut

cut的主要功能就是剪切數據

語法

cut [選項](參數)

常用選項

-f:列號,提取第幾列 -d<分隔字符>:分隔符,按照指定分隔符分割列

使用示范:獲取文本中的姓名

name age alice 21 ryan 30 cat test | cut -d ' ' -f 1


sort

sort用于對文本內容進行排序

語法

sort [選項](參數)

常用選項

-t<分隔字符>:指定排序時所用的欄位分隔字符 -n:依照數值的大小排序 -r:以相反的順序來排序 -k:指定需要排序的列

使用示范:對文本中的數據進行排序

123123 42 647 453 6789 23 1 457 97312 cat nums | sort -n


uniq

uniq命令用于對數據流進行去重,通常與sort搭配使用

語法

uniq [選項](參數)

常用參數

-c:在每列旁邊顯示該行重復出現的次數; -d:僅顯示重復出現的行列;

使用示范:統計文本中每個單詞出現的次數

the day is sunny the the the sunny is is

先去重,根據重復的次數進行排序

cat test2 | uniq -c | sort -n


tr

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 1 Line 2 Line 3 Line 4 Line 5 Line 6 Line 7 Line 8 Line 9 Line 10

你的腳本應當顯示第十行:

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

    解題思路:

  • 解法1的思路即使用sed的-n選項來只顯示匹配行,然后用p命令來輸出第十行
  • 解法2的思路是使用awk中的系統變量NR來指定行號
  • 解法3的思路是首先用tail -n +10(+為指定開始的行號)選項來獲取從第十行開始的內容,接著使用head -n 1進行過濾,即只留下第一條數據,也就是第十行的內容

  • 有效電話號碼

    leetcode-193. 有效電話號碼

    給定一個包含電話號碼列表(一行一個電話號碼)的文本文件 file.txt,寫一個 bash 腳本輸出所有有效的電話號碼。

    你可以假設一個有效的電話號碼必須滿足以下兩種格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一個數字)

    你也可以假設每行前后沒有多余的空格字符。

    示例:
    假設 file.txt 內容如下:

    987-123-4567 123 456 7890 (123) 456-7890

    你的腳本應當輸出下列有效的電話號碼:

    987-123-4567 (123) 456-7890

    答案:

    awk '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$/' file.txt

    解題思路:

  • 直接使用awk用正則表達式進行匹配即可

  • 統計詞頻

    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}'

    解題思路:

  • 由于每個單詞以空格為間隔,而結果是按行統計,所以使用tr命令將空格替換為換行符,使得每個單詞一行
  • 我們需要對出現次數進行統計,所以先使用sort對數據進行排序,使得相鄰的靠在一起,然后使用uniq進行排序,并用-c選項統計出重復的次數
  • 使用sort -nr,利用重復次數進行降序排序
  • 使用awk對文本進行處理,將單詞放在前面,次數放在后面

  • 轉置文件

    leetcode-194. 轉置文件

    給定一個文件 file.txt,轉置它的內容。
    你可以假設每行列數相同,并且每個字段由 ’ ’ 分隔.

    示例:
    假設 file.txt 文件內容如下:

    name age alice 21 ryan 30

    應當輸出:

    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

    解題思路:

  • 由題意可得,我們需要將行和列反轉過來,所以我們需要一個數組來保存每行的字符串
  • 當行號為1時,說明列號為i個單詞就是第i行的開頭
  • 當行號不為1時,將列號為i個單詞追加到數組第i項中,也就是反轉后的第i行
  • 需要注意的是,由于awk是按行讀取的,所以我們只需要一層循環來處理每一列即可
  • 總結

    以上是生活随笔為你收集整理的Shell程序设计 | 文本处理工具 :正则表达式、grep、sed、awk的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。