Linux文本處理三劍客之grep

来源:https://www.cnblogs.com/alongdidi/archive/2019/02/19/grep.html
-Advertisement-
Play Games

簡介 grep命令,用於在一個文本文件中或者從STDIN中,根據用戶給出的模式(pattern)過濾出所需要的信息。 grep以及三劍客中的另外兩個工具sed和awk都是基於行處理的,它們會一行行讀入數據,處理完一行之後再處理下一行。 簡要語法格式如下。 預設情況下,grep讀取的行數據,如果整行內 ...


簡介

grep命令,用於在一個文本文件中或者從STDIN中,根據用戶給出的模式(pattern)過濾出所需要的信息。

grep以及三劍客中的另外兩個工具sed和awk都是基於行處理的,它們會一行行讀入數據,處理完一行之後再處理下一行。

簡要語法格式如下。

grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

預設情況下,grep讀取的行數據,如果整行內容中的某部分和模式相匹配的話,就會將該行內容輸出。

例如,在/etc/passwd文件中找出包含“root”字元串的行。

該示例中的“root”字元串,就是模式。模式的強大之處在於它支持正則表達式。

例如,在/etc/passwd文件中找出以“root”或者“zwl”字元串開頭的行。

該示例中的模式的書寫就是字元串結合了正則表達式,而“^(|”字元就是正則表達式的元字元。

 

環境

CentOS 7.5

GNU grep 2.20

 

常用選項

首先我們先回顧一下語法。

grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

第一種語法是比較常用的語法,選項可以省略,如果結合管道的話,那麼文件也可以省略了。上面2個示例就是使用了該種語法。

在第二種語法中,我們見到了-e和-f選項。

-e PATTERN, --regexp=PATTERN:該選項的作用在於可以指定多個模式來匹配或者當遇到模式是以“-”開始的時候起到一個保護作用。

指定多模式的語法類似如下。

grep -e 'PATTERN1' -e 'PATTERN2' FILE

從FILE中讀取第一行,然後首先和PATTERN1匹配,匹配成功則顯示第一行併進入下一行匹配;不成功就和PATTERN2匹配,匹配成功則顯示第一行併進入下一行匹配;均不成功就進入下一行匹配。以此類推。

[root@C7 ~]# grep -e '^root' -e '^zwl' /etc/passwd

 

另外一個保護的功能,我暫不知是什麼意思,有知道的朋友可以分享一下。

-f FILE, --file=FILE:表示模式不再在CLI中指定,而是將模式寫入一個文件中,每行一個模式,然後通過-f選項讀取包含模式的文件。

--help:查看幫助。羅列了大部分選項的簡要描述,不過沒包含元字元解釋。

-V, --version:如果是向grep官方遞交bug的時候,需要帶上版本。

-G, --basic-regexp:將模式解釋為基本正則表達式,這是grep的預設行為。

-E, --extended-regexp:將模式解釋為擴展正則表達式。

-F, --fixed-strings:將模式解釋為固定的字元串,即禁用正則。雖然失去了正則的功能,但是換來性能的極大提升,當遇到大文本文件的時候相當好用。

--color=auto:將被grep所匹配到的內容給予著色處理,就像上面的截圖中所顯示的,通過正則所匹配到的字元串會被著色。由於我使用的系統是CentOS 7,該系統上的grep啟用了顯示著色的別名,因此我們不使用該選項也可以顯示顏色。

alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'

然而在CentOS 6上預設是沒有的,需要自行添加。

-i, --ignore-case:表示模式的匹配是忽略大小寫的。

[root@C7 ~]# cat grep.txt
alongdidi
ALONGdidi
xiamen
XiaMen
[root@C7 ~]# grep 'xiamen\|alongdidi' grep.txt
alongdidi
xiamen
[root@C7 ~]# grep -i 'xiamen\|alongdidi' grep.txt
alongdidi
ALONGdidi
xiamen
XiaMen

-v, --invert-match:表示反向匹配。預設是將匹配模式的行列印出來,而使用該選項的話,則是將不匹配的行列印出來。

[root@C7 ~]# cat grep.txt
alongdidi
ALONGdidi
xiamen
XiaMen
[root@C7 ~]# grep -iv 'xiamen' grep.txt
alongdidi
ALONGdidi

從這個示例中,我們也可以發現,--color=auto的著色,只會將模式所匹配到的內容進行著色,不匹配的不著色。

-o, --only-matching:表示僅列印出模式所匹配的字元,而不是將整行都列印出來。

[root@C7 ~]# grep '^root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@C7 ~]# grep -o '^root' /etc/passwd
root

-o選項的模式匹配出來的字元串個數,不等同於文本文件中對應有那麼多行匹配。

[root@C7 ~]# grep 'root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@C7 ~]# grep -o 'root' /etc/passwd
root
root
root
root

 -n, --line-number:在顯示出匹配的內容時,通過該選項,顯示匹配模式的行在輸入文件中的行號。

[root@C7 ~]# grep -n 'xiamen' grep.txt 
3:xiamen

-q, --quiet, --silent:靜默模式,不會輸出任何信息到STDOUT,即便遇到諸如文件不存在或者文件不可讀的錯誤情況,也不會輸出。匹配成功則返回0狀態碼,一般用於結合$?做判斷。

-A NUM, --after-context=NUM:列印匹配到的文本所在行以及其後面NUM行,NUM是一個正整數。

-B NUM, --before-context=NUM:列印匹配到的文本所在行以及其前面NUM行。

-C NUM, -NUM, --context=NUM:列印匹配到的文本所在行以及其上下NUM行。

[root@C7 ~]# cat grep.txt
aaa
bbb
ccc
zhongjian
ddd
eee
fff
[root@C7 ~]# grep -A 3 'zhongjian' grep.txt
zhongjian
ddd
eee
fff
[root@C7 ~]# grep -B 3 'zhongjian' grep.txt
aaa
bbb
ccc
zhongjian
[root@C7 ~]# grep -C 3 'zhongjian' grep.txt
aaa
bbb
ccc
zhongjian
ddd
eee
fff

常用選項就說到這裡,基本可以滿足日常需求,grep的真正強大之處在於與正則表達式的結合。

 

正則表達式

正則表達式可使用在grep的匹配模式當中,它由多個元字元所組成,用於匹配出用戶所期望的特定的字元串。

因此正則表達式的重點就在於元字元。

元字元

字元匹配

.:匹配任意單個字元。

[]:匹配任意範圍內的單個字元,這裡的範圍,支持類似glob的機制(詳見man 7 glob),支持字元類(character classes),如下。

  [:alnum:]:字母和數字。

  [:alpha:]:字母。

  [:digit:]:數字。

  [:lower:]:小寫字母。

  [:upper:]:大寫字母。

  [:space:]:空白字元,例如空格或者製表符。

  [:punct:]:標點符號。

  [:graph:]:非空字元。

  等等。

[^]:匹配任意範圍外的單個字元。

次數匹配

*:匹配前面的字元任意次(0次、1次或者多次)。一般是結合“.”使用,例如“.*”表示匹配任意長度的任意字元,即等同於glob中的通配符“*”。

?:匹配前面的字元0次或1次,即前面的字元可有可無。

+:匹配前面的字元1次或多次,即前面的字元至少出現1次。

{m}:匹配前面的字元m次。

  {m,n}:匹配前面的字元,至少m次,至多n次。

  {0,n}或者{,n}:匹配前面的字元,至多n次。

  {m,}:匹配前面的字元,至少m次。

位置錨定

^:錨定行首,表示模式必須出現在行的最左側。

$:錨定行尾,表示模式必須出現在行的最右側。

^PATTERN$:整行錨定,表示模式必須剛好匹配整行的內容。

  ^$:匹配空行。

\<或者\b:錨定詞首。

\>或者\b:錨定詞尾。

一般是不使用\b,因為它不能明確表示詞首或者詞尾。

\<PATTERN\>:整詞錨定。

分組及引用

():表示分組,可用於將某個模式或字元串包裹,用於次數匹配,例如“xy+”和“(xy)+”的區別。不過主要的作用是用於後向引用。

\n:表示引用,n是一個正整數,表示引用第幾個分組的內容。例如“^(root).*\1$”。分組之後可以不引用,而如果涉及了引用,那麼必定存在分組。

基本正則與擴展正則

正則表達式又分為基本正則表達式(BRE)和擴展正則表達式(ERE)。

它們的區別在於元字元支持的不同。ERE在包含了BRE的元字元的基礎上又進行了擴展。

BRE的元字元:.、[]、[^]、*、^、$、\b、\<、\>、\n(引用)。

ERE的元字元:?、+、{}、()、|。

對於Linux中的GNU grep工具來說,兩種正則是都支持的,區別在於元字元的書寫方式不同。

預設情況下,grep命令支持的是BRE,因此在書寫BRE元字元的時候不改變,在書寫ERE元字元的時候,需要在元字元前面加上轉義字元“\”。

如果通過-E選項開啟支持ERE的話,那麼在書寫BRE和ERE元字元的時候,都不需要改變。如下所示。

# grep "^\(root\)\?" /PATH/TO/FILE
# grep -E "^(root)?" /PATH/TO/FILE

因此可以每次都使用-E選項來書寫模式。

在開啟-E選項支持ERE的前提下,如果想要匹配ERE的元字元自身,例如想匹配一個問號“?”,那麼就需要加上轉義“\?”。

僅僅解釋每個元字元的作用,不好理解,通過一些示例來體會一下。

 

示例

1、找出/etc/passwd中不以“/bin/bash”結尾的行。

[root@C7 ~]# grep -v "/bin/bash$" /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
...

2、找出/etc/passwd中含有兩位數或三位數作為欄位信息的行。

[root@C7 ~]# grep -E "\<[[:digit:]]{2,3}\>" /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
...

3、找出/etc/rc.d/init.d/functions中,至少一個空白開頭並且後面跟著至少一個非空白字元的行。

[root@C7 ~]# grep -E "^[[:space:]]+[^[:space:]]+" /etc/rc.d/init.d/functions

4、找出netstat -atn命令結果中以LISTEN後跟任意個空白字元的行。

[root@C7 ~]# netstat -atn | grep "LISTEN[[:space:]]*"
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp6       0      0 :::111                  :::*                    LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 ::1:631                 :::*                    LISTEN     
tcp6       0      0 ::1:25                  :::*                    LISTEN

5、找出示例文件中,前後都包like或者love的行。

[root@C7 ~]# cat test.txt
He likes his lover.
He loves his lover.
She likes her liker.
She lovers her liker.
[root@C7 ~]# grep -E "(l..e).*\1" test.txt
He loves his lover.
She likes her liker.

6、找出/proc/meminfo文件中,所有以Mem或者mem開頭的行。

[root@C7 ~]# grep -E '^[Mm]em' /proc/meminfo
MemTotal:         997980 kB
MemFree:          168996 kB
MemAvailable:     354096 kB
[root@C7 ~]# grep -E '^(M|m)em' /proc/meminfo
MemTotal:         997980 kB
MemFree:          168996 kB
MemAvailable:     354096 kB

7、查找/etc/passwd中root、postfix和haimianbb用戶的相關信息。

[root@C7 ~]# grep -E "^(root|postfix|haimianbb)\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
haimianbb:x:1004:1005::/home/haimianbb:/bin/bash

8、找出/etc/init.d/functions文件中的函數名(可以含括弧)。

留意函數名的特征(數字字母下劃線)。留意-o選項的作用。啟用ERE之後,()有分組的含義,因此如果模式要匹配出字面意義上的()就需要使用轉義“\(\)”。

[root@C7 ~]# grep -Eo "[_[:alnum:]]+\(\)" /etc/init.d/functions
checkpid()
__kill_pids_term_kill_checkpids()
__kill_pids_term_kill()
__pids_var_run()
__pids_pidof()
daemon()
...

9、通過grep實現basename命令的功能。

[root@C7 ~]# basename /etc/init.d/functions
functions
[root@C7 ~]# basename /etc/init.d/functions/
functions
[root@C7 ~]# echo "/etc/init.d/functions" | grep -Eo "[^/]+/?$" | grep -Eo "[[:alnum:]]+"
functions
[root@C7 ~]# echo "/etc/init.d/functions/" | grep -Eo "[^/]+/?$" | grep -Eo "[[:alnum:]]+"
functions

10、通過grep實現dirname命令的功能。

不知道如何實現,期待各位博友的分享。

11、找出ifconfig命令結果中,以獨立單詞形式存在的1000以內的數字。

[root@C7 ~]# ifconfig | grep -E "\<([1-9]|[1-9][0-9]|[1-2][0-9][0-9])\>"
[root@C7 ~]# ifconfig | grep -Eo "\<([1-9]|[1-9][0-9]|[1-2][0-9][0-9])\>"

12、找出ifconfig命令結果中的IP地址。

這種判斷方式比較魯莽,並沒有針對IP地址的特性,例如每個位元組的最大十進位數是255。

[root@C7 ~]# ifconfig | grep -Eo "[[:digit:]]{,3}(\.[[:digit:]]{,3}){3}"
192.168.17.7
255.255.255.0
192.168.17.255
127.0.0.1
255.0.0.0
192.168.122.1
255.255.255.0
192.168.122.255

13、查找/etc/passwd中,用戶名等同於shell名稱的用戶信息。

[root@C7 ~]# grep -E "(^[[:alnum:]-]+\>).*\1$" /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
bash:x:1005:1006::/home/bash:/bin/bash
nologin:x:1008:1009::/home/nologin:/sbin/nologin

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Quartz.NET是一個強大、開源、輕量的作業調度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改寫,可用於winform和asp.net應用中。它靈活而不複雜。你能夠用它來為執行一個作業而創建簡單的或複雜的作業調度。它有很多特征,如:資料庫支持,集群,插件,... ...
  • C#:使用Parallel並行執行任務 1. 代碼實現 2. 運行結果: ...
  • 前幾個章節我們講到Windows Server 2016-圖形化新建域用戶(一),本章節我們簡單講解下如何通過命令批量創建域用戶,以便高效完成日常工作中實際批量創建用戶需求,內容涉及dsadd user、net user、new-aduser,具體信息如下:dsadd user創建用戶:將單個用戶添... ...
  • 摘要 運動底盤是移動機器人的重要組成部分,不像激光雷達、IMU、麥克風、音響、攝像頭這些通用部件可以直接買到,很難買到通用的底盤。一方面是因為底盤的尺寸結構和參數是要與具體機器人匹配的;另一方面是因為底盤包含軟硬體整套解決方案,是很多機器人公司的核心技術,一般不會隨便公開。出於強烈的求知欲與學習熱情 ...
  • 功能變數名稱系統(DNS)是包含TCP / IP的行業標準協議套件之一,DNS客戶端和DNS伺服器一起為電腦和用戶提供電腦名稱到IP地址映射名稱解析服務。在Windows Server 2016中,DNS是可以使用伺服器管理器或Windows PowerShell命令安裝的伺服器角色。 如果要安裝新的A... ...
  • 摘要 運動底盤是移動機器人的重要組成部分,不像激光雷達、IMU、麥克風、音響、攝像頭這些通用部件可以直接買到,很難買到通用的底盤。一方面是因為底盤的尺寸結構和參數是要與具體機器人匹配的;另一方面是因為底盤包含軟硬體整套解決方案,是很多機器人公司的核心技術,一般不會隨便公開。出於強烈的求知欲與學習熱情 ...
  • 本章節補充介紹在 Windows Server 2016 中功能變數名稱系統 (DNS) 伺服器新增或已更改的功能相關信息,具體內容如下: 功能 DNS策略 您可以將DNS策略用於基於地理位置的流量管理,基於一天中的時間的智能DNS響應,管理為裂腦配置配置的單個DNS伺服器,應用DNS查詢的過濾器等。 以下 ...
  • 問題表現如下: 1、有Hyper-V功能未關閉的可能, 隨便貼一個鏈接,網上一樣的方法很多: https://jingyan.baidu.com/article/9f63fb916b50e1c8400f0ebf.html 測試後發現我並沒有開啟這個功能。。。頭疼 接著找方法: 2、有win10安全中 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...