1. 程式人生 > >shell文字過濾程式設計(一):grep和正則表示式

shell文字過濾程式設計(一):grep和正則表示式

Linux系統中有很多檔案,比如配置檔案、日誌檔案、使用者檔案等。檔案中都包含了大量的資訊,我們可以使用cat等命令輕鬆將其輸出到螢幕,但如果要從檔案中分析或提取資料,還需要其他工具來實現。而linux正好提供了這些工具:grep、awk、sed等。把這些工具使用好,可以極大地提高你的工作效率,對系統管理員分析資料有極大幫助,而對linux開發人員來說也可以在開發測試中以及平時使用中節省不少時間。本系列文中將介紹這些工具來實現文字過濾分析。


    常用的grep選項有:
-c  只輸出匹配行的計數。
-i  不區分大小寫(只適用於單字元) 。
-h  查詢多檔案時不顯示檔名。
-l  查詢多檔案時只輸出包含匹配字元的檔名。
-n  顯示匹配行及行號。
-s  不顯示不存在或無匹配文字的錯誤資訊。
-v  顯示不包含匹配文字的所有行。
    本節文章大數示例均使用檔案/etc/passwd來作為過濾物件。
一、匹配行
最簡單(也是最常用)的用法是在一個檔案(或多個檔案)中查詢某一字串,比如在檔案/etc/passwd中查詢包含字串”user”的行:
# grep "user" /etc/passwd
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
oprofile:x:16:16:Special user account to be used by OProfile:/var/lib/oprofile:/sbin/nologin
qemu:x:107:107:qemu user:/:/sbin/nologin
radvd:x:75:75:radvd user:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
saslauth:x:994:76:"Saslauthd user":/run/saslauthd:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nm-openconnect:x:992:991:NetworkManager user for OpenConnect:/:/sbin/nologin
#
一般我們將要查詢的字串用雙引號包含起來,一是以防被誤解為 s h e l l命令,二是可以用來查詢多個單片語成的字串。
使用-c選項輸出匹配行數:
# grep -c "user" /etc/passwd
8
#
使用-n選項輸出匹配行及行號:
# grep -n "user" /etc/passwd
18:usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
19:oprofile:x:16:16:Special user account to be used by OProfile:/var/lib/oprofile:/sbin/nologin
22:qemu:x:107:107:qemu user:/:/sbin/nologin
25:radvd:x:75:75:radvd user:/:/sbin/nologin
27:tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
30:saslauth:x:994:76:"Saslauthd user":/run/saslauthd:/sbin/nologin
34:rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
38:nm-openconnect:x:992:991:NetworkManager user for OpenConnect:/:/sbin/nologin
#
其中第一列輸出行號,後面輸出行內容。
我們發現上面匹配“user”的行有的返回的是包含“rpcuser”和“trousers“的行,如果我們要精確地抽取“user”的行,可以這樣用:
# grep -n "\<user\>" /etc/passwd
18:usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
19:oprofile:x:16:16:Special user account to be used by OProfile:/var/lib/oprofile:/sbin/nologin
22:qemu:x:107:107:qemu user:/:/sbin/nologin
25:radvd:x:75:75:radvd user:/:/sbin/nologin
30:saslauth:x:994:76:"Saslauthd user":/run/saslauthd:/sbin/nologin
38:nm-openconnect:x:992:991:NetworkManager user for OpenConnect:/:/sbin/nologin
#
瞬間少了27和34行。
如果要忽略大小寫的話可以使用-i選項,如下:
[[email protected] shell_text_filter]# grep -ni "\<user\>" /etc/passwd
12:ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
17:polkitd:x:999:999:User for polkitd:/:/sbin/nologin
18:usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
19:oprofile:x:16:16:Special user account to be used by OProfile:/var/lib/oprofile:/sbin/nologin
20:colord:x:998:998:User for colord:/var/lib/colord:/sbin/nologin
22:qemu:x:107:107:qemu user:/:/sbin/nologin
25:radvd:x:75:75:radvd user:/:/sbin/nologin
30:saslauth:x:994:76:"Saslauthd user":/run/saslauthd:/sbin/nologin
34:rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
35:nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
38:nm-openconnect:x:992:991:NetworkManager user for OpenConnect:/:/sbin/nologin
 
瞬間多了幾行。
使用選項-v可以過濾不含指定字串的行:
# grep -v "a" /etc/passwd  
bin:x:1:1:bin:/bin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
nobody:x:99:99:Nobody:/:/sbin/nologin
polkitd:x:999:999:User for polkitd:/:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
unbound:x:997:997:Unbound DNS resolver:/etc/unbound:/sbin/nologin
qemu:x:107:107:qemu user:/:/sbin/nologin
openvpn:x:996:995:OpenVPN:/etc/openvpn:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
#
上面列出的行都不包含”a”。
結合使用ps命令可以查詢當前系統是否正在執行我們需要的程式,命令如下:
# ps x | grep vsftpd
1020 ?      Ss    0:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
10264 pts/1    S+    0:00 grep --color=auto vsftpd
#
但是發現列印結果包含當前shell程序,我們可以通過使用-v選項來過濾輸出結果,如下:
# ps x | grep "vsftpd" | grep -v "grep"
1020 ?      Ss    0:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
#
該方法相當常用。
二、結合使用正則表示式
其實grep過濾可以和正則表示式聯合起來用,使匹配加入一些規則,這樣的使用更為靈活。使用正則表示式時最好用單引號括起來,這樣可以防止 g r e p中使用的專有模式與一些shell命令的特殊方式相混淆。
這裡我們先講一下正則表示式,下面是正則表示式基本元字符集及其含義:
^ 只只匹配行首
$ 只只匹配行尾
* 只一個單字元後緊跟*,匹配0個或多個此單字元
[ ] 只匹配[ ] 內字元。可以是一個單字元,也可以是字元序列。可以使用 -表示[ ]內字元序列範圍,如用 [ 1 - 5 ]代替[ 1 2 3 4 5 ]
\ 只用來遮蔽一個元字元的特殊含義。因為有時在 s h e l l中一些元字元有
特殊含義。\可以使其失去應有意義
. 只匹配任意單字元
p a t t e r n \ { n \ } 只用來匹配前面 p a t t e r n出現次數。n為次數
p a t t e r n \ { n,\ } m 只含義同上,但次數最少為 n
p a t t e r n \ { n,m \ } 只含義同上,但 p a t t e r n出現次數在n與m之間。
句點“.”可以匹配任意單字元。“.”允許匹配A S C I I集中任意字元,或為字母,或為數字。
比如:
# grep '.mm..' /etc/passwd
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
#
# grep 'm..l' /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
#
在行首以^匹配字串或字元序列,^只允許在一行的開始匹配字元或單詞。
比如匹配以ma開頭的行:
# grep '^ma' /etc/passwd   
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
#
正則表示式可以將各種模式混合使用:
# grep '^ma....ll' /etc/passwd
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
#
^在正則表示式中使用頻繁,因為大量的抽取操作通常在行首。
在行尾以$匹配字串或字元, $與^正相反,它在行尾匹配字串或字元, $符號放在匹配單詞後。比如匹配以bash結尾的行:
# grep 'bash$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
allen:x:1000:1000:allen:/home/allen:/bin/bash
aln:x:1001:1001::/home/aln:/bin/bash
#
如果要匹配所有空行,執行以下操作:
^ $
具體分析為匹配行首,又匹配行尾,中間沒有任何模式,因此為空行。
如果只返回包含一個字元的行,操作如下:
^ . $
不像空白行,在行首與行尾之間有一個模式,代表任意單字元。
使用*匹配字串中的單字元或其重複序列,使用此特殊字元匹配任意字元或字串的重複多次表示式。
使用[]匹配一個範圍或集合,可以用逗號將括弧內要匹配的不同字串分開,使用“ - ”表示一個字串範圍,表明字串範圍從“ -”左邊字元開始,到“ - ”右邊字元結束。
比如要匹配包含aln或all的行,可以如下寫:
# grep 'al[l,n]' /etc/passwd
allen:x:1000:1000:allen:/home/allen:/bin/bash
aln:x:1001:1001::/home/aln:/bin/bash
#
忽略大小寫的也可以由另外一種方式:
# grep 'System' /etc/passwd
dbus:x:81:81:System message bus:/:/sbin/nologin
pulse:x:995:994:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
[[email protected] shell_text_filter]# grep '[Ss]ystem' /etc/passwd
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-journal-gateway:x:191:191:Journal Gateway:/var/log/journal:/usr/sbin/nologin
pulse:x:995:994:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
#
使用\{\}匹配模式結果出現的次數,使用*可匹配所有匹配結果任意次,但如果只要指定次數,就應使用 \ { \ } ,此模式有三種形式,即:
pattern\{n\}  匹配模式出現n次。
pattern\{n,\}  匹配模式出現最少 n次。
pattern\{n,m}  匹配模式出現n到m次之間,n , m為0 - 2 5 5中任意整數。
過濾字元m至少出現2次的行:
# grep 'm\{2,\}' /etc/passwd
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
#
過濾9出現2次,並以4結尾的行:
# grep '9\{2,\}4' /etc/passwd
pulse:x:995:994:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
saslauth:x:994:76:"Saslauthd user":/run/saslauthd:/sbin/nologin
#
grep命令加-E引數,這一擴充套件允許使用擴充套件模式匹配。比如要獲取包含allen或aln的行,可以這樣用。
# grep -E 'allen|aln' /etc/passwd  
allen:x:1000:1000:allen:/home/allen:/bin/bash
aln:x:1001:1001::/home/aln:/bin/bash
#

相關推薦

shell文字過濾程式設計grep表示式

Linux系統中有很多檔案,比如配置檔案、日誌檔案、使用者檔案等。檔案中都包含了大量的資訊,我們可以使用cat等命令輕鬆將其輸出到螢幕,但如果要從檔案中分析或提取資料,還需要其他工具來實現。而linux正好提供了這些工具:grep、awk、sed等。把這些工具使用好,可以

shell文字過濾程式設計awk之迴圈判斷及陣列

與上一節printf一樣,awk的迴圈判斷和C語言的迴圈判斷語法極其類似。 1、 While迴圈 #!/bin/sh awk ' BEGIN { ORS="" } { i=0 while (i < NF) { printf

jmeter教程關聯及表示式提取器

所謂關聯,就在從前面請求的響應中提取資料,給後面的請求使用。而提取資料,則需要用到後置處理器裡的正則表示式提取器。為了演示,我簡單寫了一個java請求,模擬介面的響應資料 響應的資料為一個json,這是模擬介面查詢會員列表的資料。time是查詢資料花費的時間,count是查詢出了多少條資料

網路程式設計埠那些事兒

TCP和UDP協議都存在一個叫做埠的東西,但埠卻不是IP協議的一部分。 埠被設計出來主要是為了給協議棧和應用對應: 協議棧用埠號將資料分配給不同的應用層程式 應用層程式用埠號去區分不同的連線,參見之前提到過的“四元組” TCP和UDP協議都使用了埠號(Port num

Python函數語言程式設計高階函式

首先有一個高階函式的知識。 一個函式可以接收另一個函式作為引數,這種函式就稱之為高階函式。 def add(x, y, f): return f(x) + f(y) 當我們呼叫add(-5, 6, abs)時,引數x,y和f分別接收-5,6和abs,根據函式定義,我們可以推導計算過程為:

併發程式設計執行緒基礎、執行緒之間的共享與協作

一、基礎概念 1.1 CPU核心數、執行緒數 **兩者的關係:**cpu的核心數與執行緒數是1:1的關係,例如一個8核的cpu,支援8個執行緒同時執行。但在intel引入超執行緒技術以後,cpu與執行緒數的關係就變成了1:2。此外在開發過程中並沒感覺到執行緒的限制,那是因為cpu

Windows網路程式設計TCP/IP協議

概述 這個協議是一個四層協議: 應用層,主要協議有HTTP、FTP等 傳輸層,主要協議有TCP、UDP等 網路層,主要協議有IP等 鏈路層,主要協議有ICMP等 下層中的協議總是為上層中的協議服務的,比如說應用層的HTTP、FTP協議都是基於T

HalconC#混合程式設計數字識別

Halcon匯出C#程式碼 using System; using HalconDotNet; public partial class HDevelopExport { public HTuple hv_ExpDefaultWinHandle; //

Java WebSocket程式設計EchoServer應用

通過一個簡單的示例(EchoServer應用)來了解Java WebSocket原理。這是一個客戶端/伺服器應用,客戶端是Web瀏覽器上的一小段JavaScript,伺服器是一個WebSocket端點。 執行環境:Java 8 ,Eclipse Java EE ,Tomcat 9.0

C語言面向物件程式設計封裝與繼承

最近在用 C 做專案,之前用慣了 C++ ,轉回頭來用C 還真有點不適應。 C++ 語言中自帶面向物件支援,如封裝、繼承、多型等面向物件的基本特徵。 C 原本是面向過程的語言,自身沒有內建這些特性,但我們還是可以利用 C 語言本身已有的特性來實現面向物件的一些基本特徵。接下來

Javascript 面向物件程式設計封裝

Javascript是一種基於物件(object-based)的語言,你遇到的所有東西幾乎都是物件。但是,它又不是一種真正的面向物件程式設計(OOP)語言,因為它的語法中沒有class(類)。 那麼,如果我們要把"屬性"(property)和"方法"(method),封裝成

深度文字匹配模型k-nrm

開篇 用深度學習模型去匹配句子的相似度已經是目前句子相似度的主流方法。本質上還是句子相似度的問題。深度文字匹配模型可以提供更好的搜尋排序服務。它的基本場景就是:給一個query,模型返回排序靠前的document。是不是很像一個搜尋引擎,其實本質上是差不多的。只

Javascript模組化程式設計模組的寫法

隨著網站逐漸變成"網際網路應用程式",嵌入網頁的Javascript程式碼越來越龐大,越來越複雜。 網頁越來越像桌面程式,需要一個團隊分工協作、進度管理、單元測試等等......開發者不得不使用軟體工程的方法,管理網頁的業務邏輯。 Javascript模組化程式設計,

Linux網路程式設計一個簡單的socket程式

伺服器: /* *tcp_server.c */ #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include

大學生學程式設計為什麼要選擇做名程式設計師?

從這篇文章開始準備做一個大學生學程式設計系列文章,主要幫助一些還在程式設計路上徘徊的小夥伴,作為一個過來人的身份總結一些程式設計經驗以及心得,在自學的過程中走了很多的彎路,在此通過這個專欄分享給需要程式設計的小夥伴。 無數個人心中都有一個程式設計夢,想著自己能夠做在電腦旁邊敲程式碼,做出

使用gensimsklearn搭建一個文字分類器流程概述

總的來講,一個完整的文字分類器主要由兩個階段,或者說兩個部分組成:一是將文字向量化,將一個字串轉化成向量形式;二是傳統的分類器,包括線性分類器,SVM, 神經網路分類器等等。 之前看的THUCTC的技術棧是使用 tf-idf 來進行文字向量化,使用卡方校驗(c

windows基礎應用程式程式設計基本框架

從一開始程式設計時,大家面對著黑乎乎的控制檯視窗,就開始幻想什麼時候能進入windows下進行程式設計。能夠編寫出具有形形色色視窗的人往往都被我們認為是牛人。而從控制檯視窗進入windows下進行程式設計,對於初學者來講,絕對是一個很難跨越的坎。對此,自己也深有體會。因此,

JAVA 8函數語言程式設計高階函式

函數語言程式設計的核心在高階函式與偏函式,在JAVA 8中,提供了很多函式式的介面,但跟Python、Javascript的函式相比較,還是存在較大的距離。 首先看一個高階函式的例子,這裡利用區域性變數域特性,進行延遲求值,如下: /** * 輸入一

UART0串列埠程式設計通訊協議設計;RS232標準

UART0串列埠程式設計(一) 嵌入式系統之間採用通訊方式交換資料,序列通訊是一種最基本的通訊手段。現在由於各類CPU均集成了UART部件。本節對串列埠程式設計時如何設計串列埠通訊協議,以及對RS232介面進行了說明。 1.    通訊協議設計 在進行通訊時,每次需要傳送的

c++11多執行緒程式設計建立執行緒的三種方法

c++11執行緒庫原始的c++標準僅支援單執行緒程式設計,新的c++標準(c++11或c++0x)於2011年釋出,引入了新的執行緒庫。 編譯器要求 Linux: gcc 4.8.1 (完全併發支援) Windows: Visual Studio 2012 and Min