【shell筆記>命令】grep,sed,awk

weixin_34146805發表於2017-04-09

grep

grep的基本用法

grep命令是支援正規表示式的一個多用途文字搜尋工具,一般格式為

grep 選項 模式 檔案

選項 意義
-c 只輸出匹配行的數量
-i 搜尋時忽略大小寫
-h 查詢多檔案時不顯示檔名
-l 只列出符合匹配的檔名,而不列出具體的匹配行
-n 列出所有的匹配行,並顯示行號
-s 不顯示不存在或無匹配文字的錯誤資訊
-v 顯示不包含匹配文字的所有行
-w 匹配整詞
-x 匹配正行
-r 遞迴搜尋,不僅搜尋當前目錄,而且搜尋子目錄
-q 禁止輸出任何結果,以退出狀態表示搜尋是否成功
-b 列印匹配行距檔案頭部的偏移量,以位元組為單位
-o 與-b選項結合使用,列印匹配的詞距檔案頭部的偏移量,以位元組為單位
-E 支援擴充套件的正規表示式
-F 不支援正規表示式,按照字串的字面意思進行匹配

grep命令的模式十分靈活,可以是字串,也可以是變數,還可以是正規表示式。注意,無論模式是何種形式,只要模式中包含空格,就需要使用雙引號將模式引起來。

grep與正規表示式

  1. 匹配行首,用元字元^
  1. 設定大小寫,用-i

  2. 匹配重複字元,用., *

  3. 轉義符,用\

  4. POSIX字元類

    類名 意義
    [:upper:] 表示大寫字母[A~Z]
    [:lower:] 表示小寫字母[a~z]
    [:digit:] 表示阿拉伯數字[0~9]
    [:alnum:] 表示大小寫字母和阿拉伯數字
    [:space:] 表示空格鍵和TAB鍵
    [:alpha:] 表示大小寫字母
    [:cntrl:] 表示Ctrl
    [:graph:]或[:print:] 表示ASCII碼
    [:xdigit:] 表示16進位制數字[09AFa~f]
  5. 精確匹配:用\<\>

  6. 或字元,grep需要加上-E選項才能支援它,用|表示

grep命令族

grep: 標準grep命令

egrep: 擴充套件grep命令,支援基本和擴充正規表示式

fgrep: 快速grep命令,不支援正規表示式


sed命令

sed是一個非互動式文字編輯器,它可對文字檔案和標準輸入進行編輯,標準輸入可以是來自鍵盤輸入、檔案重定向、字串、變數,甚至來自管道的文字。sed適用於以下三中場合:

  • 編輯相對互動式文字編輯器而言太大的檔案。
  • 編輯命令太複雜,在互動式文字編輯器中難以輸入的情況。
  • 對檔案掃描一遍,但是需要執行多個編輯函式的情況。

基本用法

sed只是對緩衝區中原始檔案的副本進行編輯,並不編輯原始檔案。如果需要儲存檔案改動的內容,需要將輸出重定向到另一個檔案。

呼叫sed有三種方式,一種為Shell命令列方式,另外兩種是將sed命令寫入指令碼檔案,然後執行該指令碼檔案。

  1. 在Shell命令列輸入命令呼叫sed,格式為sed [選項] 'sed命令' 輸入檔案
  2. sed命令插入指令碼檔案後,然後通過sed命令呼叫它,格式為sed [選項] -f sed 指令碼檔案 輸入檔案
  3. sed命令插入指令碼檔案後,最常用的方法是設定該指令碼檔案為可以執行,然後直接執行該指令碼檔案,格式為./sed指令碼檔案 輸入檔案

第三種方式指令碼檔案需要以sha-bang(#!)符號開頭。無論哪種方式,如果沒有指定輸入檔案,sed將從標準輸入接收輸入。常用選項有三個

選項 意義
-n 不列印所有的行到標準輸出
-e 表示將下一個字串解析為sed編輯命令,如果只傳遞一個,可以省略
-f 表示正在呼叫sed指令碼檔案

sed命令主要由定位文字行和sed編輯命令兩部分組成,有兩種方式定位文字:

  • 使用行號,指定一行,或者指定行號範圍
  • 用正規表示式
選項 意義
x x為指定行號
x,y 指定從x到y的行號範圍
/pattern/ 查詢包含模式的行
/pattern/pattern/ 查詢包含兩個模式的行
/pattern/,x 從pattern匹配行到x號行
x,/pattern/ 上一條反過來
x,y! 查詢不包括x和y行號的行

編輯命令

選項 意義
p 列印匹配行
= 列印檔案行號
a\ 在定位行號後追加文字資訊
i\ 在定位行號之前插入文字資訊
d 刪除定位行
c\ 用新文字替代定位文字
s 使用替換模式替換相應模式
r 從另一個檔案中讀文字
w 將文字寫入到一個檔案
y 變換字元
q 第一個模式匹配後退出
l 顯示與八進位制ASCII碼等價的控制字元
{} 在定位行執行的命令組
n 讀取下一個輸入行,用下一個命令處理新的行
h 將模式緩衝區的文字複製到保持緩衝區
H ...追加到保持緩衝區
x 互換模式緩衝區和保持緩衝區內容
g 將保持模式緩衝區的內容複製到模式緩衝區
G ....追加到模式緩衝區

示例

測試檔案內容:

    This is a Certificate Request file:

    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

    /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus

    The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
    To install this user certificate, please save this e-mail message into the following file.

    /home/alloy/linuxshell/CH02/usercert.pem

sed -n: 不列印sed編輯物件的全部內容

wsx@wsx-ubuntu:~/桌面$ sed -n '1p' input
    This is a Certificate Request file:

wsx@wsx-ubuntu:~/桌面$ sed '1p' input
    This is a Certificate Request file:
    This is a Certificate Request file:

    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

    /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus

    The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
    To install this user certificate, please save this e-mail message into the following file.

    /home/alloy/linuxshell/CH02/usercert.pem

利用sed命令列印範圍行:

wsx@wsx-ubuntu:~/桌面$ sed -n '3,6p' input 
    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

sed -e: sed傳遞多個編輯命令時使用

wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/=' input 
1
6

wsx@wsx-ubuntu:~/桌面$ sed -n -e '/Certificate/p' input  -e '/Certificate/=' input
    This is a Certificate Request file:
1
    Certificate Subject:
6


sed -f:呼叫sed指令碼檔案時才起作用

wsx@wsx-ubuntu:~/桌面$ sed '/file:/a\We append a new line.' input 
    This is a Certificate Request file:
We append a new line.

    It should be mailed to zawu@seu.edu.cn

    =====================================================
    Certificate Subject:

    /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus

    The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
    To install this user certificate, please save this e-mail message into the following file.

    /home/alloy/linuxshell/CH02/usercert.pem

指令碼用法:

#! /bin/sed -f 
/file:/a\       #a\表示在此處新增文字

# 新增文字
We append a new line.\
We append a another line.

sed基本編輯命令可以放在單引號內,也可放在單引號外。

sed文字定位的一組例子

  1. 匹配元字元,用轉義符\進行遮蔽

    wsx@wsx-ubuntu:~/桌面$ sed -n '/\./p' input 
     It should be mailed to zawu@seu.edu.cn
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
     /home/alloy/linuxshell/CH02/usercert.pem
    
    
  2. 使用元字元進行匹配

    $在sed命令中表示最後一行

    wsx@wsx-ubuntu:~/桌面$ sed -n '$p' input
     /home/alloy/linuxshell/CH02/usercert.pem
    
  3. !符號,列印不在2-10的行

    wsx@wsx-ubuntu:~/桌面$ sed -n '2,10!p' input 
     This is a Certificate Request file:
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    
  4. 使用行號和關鍵字匹配限定行範圍

    wsx@wsx-ubuntu:~/桌面$ sed -n '/seugrid/,$p' input 
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    

sed基本編輯命令的一組例子

  1. 插入文字:執行指令碼,以輸入檔名作為引數

    #!/bin/sed -f
    /file:/i\             # i\表示此處換行插入文字
    We insert a new line.
    
  2. 修改文字

    #!/bin/sed -f
    
    /file:/c\             #c\表示此處換行修改文字
    We modify this line      #修改文字內容
    
  3. 刪除文字,符號是d,不帶\,與其他命令有所區別,非常靈活。下面刪除第一行和最後一行。

    wsx@wsx-ubuntu:~/桌面$ sed '1d' input
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
     Certificate Subject:
    
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    wsx@wsx-ubuntu:~/桌面$ sed '$d' input
     This is a Certificate Request file:
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
     Certificate Subject:
    
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
    
  4. 替換文字,格式s/被替換的字串/新字串/[替換選項]

    選項 意義
    g 全域性匹配替換(替換所有的)
    p 與-n選項結合,只列印替換行
    w 檔名 表示將輸出定向到一個檔案
    sx@wsx-ubuntu:~/桌面$ sed 's/Certificate/CERTIFICATE/' input
     This is a CERTIFICATE Request file:
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
     CERTIFICATE Subject:
    
     /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
     To install this user certificate, please save this e-mail message into the following file.
    
     /home/alloy/linuxshell/CH02/usercert.pem
    wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/p' input
     This is a CERTIFICATE Request file:
     CERTIFICATE Subject:
    
  5. 寫入到一個新檔案

    wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/pg' input
     This is a CERTIFICATE Request file:
     CERTIFICATE Subject:
    wsx@wsx-ubuntu:~/桌面$ 
    wsx@wsx-ubuntu:~/桌面$ sed -n '1,5 w output' input
    wsx@wsx-ubuntu:~/桌面$ cat output 
     This is a Certificate Request file:
    
     It should be mailed to zawu@seu.edu.cn
    
     =====================================================
    
    
  6. 從檔案中可讀入文字,格式指定地址 r 檔名

  7. 退出命令:q

  8. 變換命令:sed命令的y表示字元變換(不等長時會報錯)

    wsx@wsx-ubuntu:~/桌面$ sed 'y/fmj/FMJ/' input 
     This is a CertiFicate Request File:
    
     It should be Mailed to zawu@seu.edu.cn
    
     =====================================================
     CertiFicate SubJect:
    
     /O=Grid/OU=GlobusTest/OU=siMpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
    
     The above string is known as your user certiFicate subJect, and t uniquely identiFies theis user. $88
     To install this user certiFicate, please save this e-Mail Message into the Following File.
    
     /hoMe/alloy/linuxshell/CH02/usercert.peM
    
    
  9. 顯示控制字元:控制字元就是非列印字元,如退格鍵、F1鍵等。使用sed l命令。

  10. 在命令列執行命令組,用{}符號,與-e選項功能類似。

    wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/{p;=}' input
        This is a Certificate Request file:
    1
        Certificate Subject:
    6
    

awk程式設計

awk是三位前輩開發的程式語言,awk是三位建立者的首字母。基本語言與C類似。

目前,使用的是gawk,Linux系統中/bin目錄下有awkgawk兩個命令,前者實際上是後者的連結。利用gawk語言可以實現資料查詢、抽取檔案中的資料、建立管道流命令等功能。

我們可以簡單地將awk程式設計模型分位三個階段:

  • 讀輸入檔案執行的執行程式碼段(由BEGIN關鍵字標識)
  • 讀取輸入檔案時執行程式碼段
  • 讀輸入檔案之後的執行程式碼段(由END關鍵字標識)

呼叫方法分為兩種:Sehll命令列方式;指令碼執行。

awk模式匹配

任何awk語句都由模式和動作組成。模式是一組用於測試輸入行是否需要執行動作的規則,動作是包含語句、函式和表示式的執行過程。awk支援所有的正規表示式元字元,以及?+兩個擴充套件元字元。

wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print "This is a blank line."}' input
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.

單引號中間為awk命令,由兩部分組成,以“/”符號分隔,^$是模式,花括號部分是動作。該awk表示一旦讀入的輸入檔案是空行,就列印後面的字串This is a blank line

使用指令碼(將命令輸入一個檔案中):

wsx@wsx-ubuntu:~/桌面$ awk -f src.awk input
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.

內容不止這些,我們先談談其他概念。

記錄和域

awk認為輸入檔案是結構化的,awk將每個輸入檔案行定義為記錄,行中的每一個字串定義為域,域之間用空格、TAB鍵或其他符號進行分隔,分隔域的符號就叫分隔符。(這個結構化概念需要理解,很多命令和程式設計中都有涉及)

wsx@wsx-ubuntu:~/桌面$ awk '{print $2,$1,$4,$3}' sturecord 
Hao Li 025------------ njue
Ju Zhang 025---------- nju
Bin Wang 025------ seu
wsx@wsx-ubuntu:~/桌面$ awk '{print $0}' sturecord 
Li Hao  njue 025------------ 
Zhang Ju    nju 025---------- 
Wang Bin    seu 025------

可以通過對域的操作對文字進行重新排列,也可以用print $0輸入所有域。

wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {one=1;two=2}{print $(one+two)}' sturecord 
njue
nju
seu

BEGIN欄位中定義onetwo兩個變數並賦值。

-F選項用來改變分隔符,例如只以'\t'為分隔符。

wsx@wsx-ubuntu:~/桌面$ awk -F'\t' '{print $2}' sturecord 
025------------ 
025---------- 
025------

注意-F-f的區別。

awk還提供了另一種更方便的方法改變分隔符。

wsx@wsx-ubuntu:~/桌面$ cat sturecord 
Li Hao,njue,025------------ 
Zhang Ju,nju,025---------- 
Wang Bin,seu,025------
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=","}{print $1, $3}' sturecord 
Li Hao 025------------ 
Zhang Ju 025---------- 
Wang Bin 025------

關係和布林運算子

awk定義了一組關係運算子用於awk模式匹配。如下表

運算子 意義
< 小於
> 大於
<= 小於或等於
>= 大於或等於
== 等於
!= 不等於
~ 匹配正規表示式
!~ 不匹配正規表示式

用/etc/passwd檔案做個例子

# 第1域匹配root
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd
# 全部域匹配root
root:x:0:0:root:/root:/bin/bash
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
# 全部域不匹配nologin
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0!~/nologin/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin

awk條件語句與C類似,有if語句,if/else語句以及if/else else語句三種。

下面是支援的布林運算子

運算子 意義
|| 邏輯或
&& 邏輯與
! 邏輯非
# 多條件精確匹配
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3==10||$4==10) print $0}' /etc/passwd
# 多條件模糊匹配
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3~10||$4~10) print $0}' /etc/passwd
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false
whoopsie:x:109:116::/nonexistent:/bin/false
avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
wsx:x:1000:1000:wsx,,,:/home/wsx:/bin/bash
nx:x:123:1001::/var/NX/nx:/etc/NX/nxserver

表示式

一個awk表示式可以由數值、字元常量、變數、操作符、函式和正規表示式自由組合而成。

運算子 意義
+
-
*
/
%
^或** 乘方
++x 在返回x之前,x變數加1
x++ 在返回x之後,x變數加1
wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print x+=1}' input
1
2
3
4
5

系統變數

awk定義了很多內建變數用於設定環境資訊,我們稱為系統變數。分為兩種:一種用於改變awk的預設值,例如域分隔符;第二種用於定義系統值,在處理文字時可以讀取這些系統值。

變數名 意義
$n 當前記錄的第n個域,域用FS分隔
$0 記錄的所有域
ARGC 命令列引數的數量
ARGIND 命令列中當前檔案的位置(從0開始標號)
ARGV 命令列引數的陣列
CONVFMT 數字轉換格式
ENVIRON 環境變數關聯陣列
ERRNO 最後一個系統錯誤的描述
FIELDWIDTHS 欄位寬度列表,以空格鍵分隔
FILENAME 當前檔名
FNR 瀏覽檔案的記錄數
FS 欄位分隔符,預設是空格鍵
IGNORECASE 布林變數,如果為真,則進行忽略大小寫的匹配
NF 當前記錄中的域數量
NR 當前記錄數
OFMT 數字的輸出格式
OFS 輸出域分隔符,預設是空格鍵
ORS 輸出記錄分隔符,預設是換行符
RLENGTH 由match函式所匹配的字串長度
RS 記錄分隔符,預設是空格鍵
RSTART 由match函式所匹配的字串的第1個位置
SUBSEP 陣列下標分隔符,預設值是\034

格式化輸出

awk借鑑C語言的語法,定義了printf輸出語句。基本語法如下:

printf(格式控制符, 引數)

格式控制符分為修飾符和格式符兩種,如下:

修飾符 意義
- 左對齊
width 域的步長
.prec 小數點右邊的位數
運算子 意義
%c ASCII字元
%d 整型數
%e 浮點數,科學計數法
%f 浮點數
%o 八進位制數
%s 字串
%x 十六進位制數

內建字串函式

awk提供了強大的內建字串函式,用於實現文字的字串替換、查詢以及分隔等功能,下表列出:

函式名 意義
gsub(r,s) 在輸入檔案中用s替換r
gsub(r,s,t) 在t中用s替換r
index(s,t) 返回s中字串第一個t的位置
length(s) 返回s的長度
match(s,t) 測試s是否包含匹配t的字串
split(r,s,t) 在t上將r分為序列s
sub(r,s,t) 將t中第1次出現的r替換為s
substr(r,s) 返回字串r中從s開始的字尾部分
substr(r,s,t) 返回字串r中從s開始長度為t的字尾部分

向awk指令碼傳遞引數

awk指令碼內的變數可以在命令列中進行賦值,實現向awk指令碼傳遞引數,變數賦值放在指令碼之後、輸入檔案之前,格式為:

awk指令碼 parameter=value 輸入檔案

條件語句和迴圈語句

看起來基本和C一樣,框架如下——

if (條件表示式)
    動作1
[else
    動作2]
while(條件表示式)
    動作
do
    動作
while(條件表示式)
for(設定計數器初值; 測試計數器; 計數器變化)
    動作

陣列

陣列是儲存一系列值的變數,可通過索引來訪問陣列的值,索引需要用中括號括起,陣列的基本格式為:

array[index]=value

形式和C一樣,但awk陣列無需定義陣列型別和大小,可以直接賦值後使用。一般用在for迴圈中

for (variable in array)
    do somethng with array[variable]

更多操作可以檢視:http://man.linuxde.net/awk

參考:Linux Shell程式設計——從初學到精通(第2版)

相關文章