本文講述了linux系統中常用的文本提取命令cut,sed與awk的命令使用方法。借用了前輩的文章,非常感謝。
cut用法:
原文鏈接:http://blog.csdn.net/u011003120/article/details/52190187
一、作用
cut命令是一個選取命令,其功能是將文件中的每一行”字節” ”字符” ”字段” 進行剪切,選取我們需要的,並將這些選取好的數據輸出至標準輸出
二、格式
cut -[n]b file
cut -c file
cut -d[分隔符] -f[域] file
三、參數解釋
-b(bytes) :以字節爲單位進行分割。這些字節位置將忽略多字節字符邊界,除非也指定了 -n 標誌。
-c(characters) :以字符爲單位進行分割。
-d :自定義分隔符,默認爲製表符。
-f(filed) :與-d一起使用,指定顯示哪個區域。
-n :取消分割多字節字符。僅和 -b 標誌一起使用。如果字符的最後一個字節落在由 -b 標誌的 List 參數指示的
範圍之內,該字符將被寫出;否則,該字符將被排除。
四、實例分析
新建一個test1.txt,如下
557adfhg
bcd5464b
135465453456
233546576
[root@localhost shell]#
新建一個test2.txt,如下
[root@localhost shell]# cat test2.txt
星期一
星期二
星期三
星期四
星期五
星期六
星期日
[root@localhost shell]#
1) -b
1.剪切單個字節
如下,只剪切txt中的每一行的第一個字節
[root@localhost shell]# cut -b 1 test1.txt
5
b
1
2
[root@localhost shell]#
2.剪切多個字節
剪切多個字符有很多方式,
如 -b 1,3,5 //剪切每一行第 1 3 5個字符 (示例1)
如 -b 1-5 //剪切每一行第 1-5 個字符 (示例2)
如 -b -5 //剪切每一行第 1-5 個字符 (示例3)
如 -b 3- //剪切每一行第 3個字符以後的 (示例4)
示例1:
[root@localhost shell]# cut -b 1,3,5 test1.txt
57d
bd4
156
234
[root@localhost shell]#
示例2:
[root@localhost shell]# cut -b 1-5 test1.txt
557ad
bcd54
13546
23354
[root@localhost shell]#
示例3:
[root@localhost shell]# cut -b -5 test1.txt
557ad
bcd54
13546
23354
[root@localhost shell]#
示例4:
[root@localhost shell]# cut -b 3- test1.txt
7adfhg
d5464b
5465453456
3546576
[root@localhost shell]#
3.剪切字符
首先按照上面的例子對test2.txt進行操作,看有什麼現象
[root@localhost shell]# cut -b 2 test2.txt
�
�
�
�
�
�
�
[root@localhost shell]#
出現了亂碼的現象,因爲-b 只是針對字節進行裁剪,對一個漢字進行字節裁剪,得到的結果必然是亂碼,若想使用 -b 命令對字節進行裁剪,那麼則需要使用 -n 選項,此選項的作用是取消分割多字節字符。
[root@localhost shell]# cut -nb 3 test2.txt
星
星
星
星
星
星
[root@localhost shell]# cut -nb 3,6 test2.txt
星
星期
星期
星期
星期
星期
星期
[root@localhost shell]# cut -nb 3,6,9 test2.txt
星期
星期二
星期三
星期四
星期五
星期六
星期日
[root@localhost shell]# cut -nb 3,6,9,12 test2.txt
星期一
星期二
星期三
星期四
星期五
星期六
星期日
[root@localhost shell]#
2) -c
-c的作用就是剪切字符,和上面的 -nb 有些類似
[root@localhost shell]# cut -c 1 test2.txt
星
星
星
星
星
星
[root@localhost shell]# cut -c 2 test2.txt
星
期
期
期
期
期
期
[root@localhost shell]# cut -c 1-3 test2.txt
星期
星期二
星期三
星期四
星期五
星期六
星期日
[root@localhost shell]#
3)-f
上面的-b -c 只是針對於格式固定的數據中剪切,但是對於一些格式不固定的,就沒有辦法獲取到我們想要的數據,因此便有了 -f 域的概念。
示例1:
[root@localhost shell]# cat /etc/passwd | head -n 3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@localhost shell]#
例如將上面的第一個 : 前面的字符給剪切出來,那麼我們就可以使用 -d 命令,指定其分割符爲 : 然後再選取第一個域內的內容即可,如下
[root@localhost shell]# cat /etc/passwd | head -n 3 | cut -d : -f 1
root
bin
daemon
[root@localhost shell]#
示例2:
剪切ip地址,如下:
[root@localhost shell]# ifconfig eth0 | grep "inet addr"
inet addr:192.168.1.199 Bcast:192.168.1.255 Mask:255.255.255.0
[root@localhost shell]# ifconfig eth0 | grep "inet addr" | cut -d : -f 2
192.168.1.199 Bcast //以 : 爲分隔符,選取第二個域裏面的內容,輸出
[root@localhost shell]# ifconfig eth0 | grep "inet addr" | cut -d : -f 2 | cut -d ' ' -f 1
192.168.1.199 //以空格爲分割符,選取第一個域內的內容,輸出
[root@localhost shell]#
sed用法:
初次學習請拿這個飛機票:http://www.cnblogs.com/dong008259/archive/2011/12/07/2279897.html
詳細解釋如下:
1,sed介紹sed可刪除(delete)、改變(change)、添加(append)、插入(insert)、合、交換文件中的資料行,或讀入其它檔的資料到文>件中,也可替換(substuite)它們其中的字串、或轉換(tranfer)其中的字母等等。例如將文件中的連續空白行刪成一行、"local"字串替換成"remote"、"t"字母轉換成"T"、將第10行資料與第11資料合等.
總合上述所言,當sed由標準輸入讀入一行資料並放入pattern space時,sed依照sed script 的編輯指令逐一對pattern space內的資料執行編輯,之後,再由pattern space內的結果送到標準輸出,接着再將下一行資料讀入.如此重執行上述動作,直至讀>完所有資料行爲止.
小結,記住:
(1)sed總是以行對輸入進行處理
(2)sed處理的不是原文件而是原文件的拷貝
命令行概述:
sed 編輯指令的格式如下 :
[address1[,address2]]function[argument]
其中 , 位址參數 address1 、address2 爲行數或 regular expression 字串 , 表示所執行編輯的資料行; 函數參數 function[argument] 爲 sed 的內定函數 , 表示執行的編輯動作。
有那些函數(function)參數
下頁表中介紹所有 sed 的函數參數(參照[chapter 4])的功能。
函數參數 功能
: label 建立 script file 內指令互相參考的位置。
# 建立解
{ } 集合有相同位址參數的指令。
! 不執行函數參數。
= 印出資料行數( line number )。
a/ 添加使用者輸入的資料。
b label 將執行的指令跳至由 : 建立的參考位置。
c/ 以使用者輸入的資料取代資料。
d 刪除資料。
D 刪除 pattern space 內第一個 newline 字母 / 前的資料。
g 拷貝資料從 hold space。
G 添加資料從 hold space 至 pattern space 。
h 拷貝資料從 pattern space 至 hold space 。
H 添加資料從 pattern space 至 hold space 。
l 印出 l 資料中的 nonprinting character 用 ASCII 碼。
i/ 插入添加使用者輸入的資料行。
n 讀入下一筆資料。
N 添加下一筆資料到 pattern space。
p 印出資料。
P 印出 pattern space 內第一個 newline 字母 / 前的資料。
q 跳出 sed 編輯。
r 讀入它檔內容。
s 替換字串。
t label 先執行一替換的編輯指令 , 如果替換成牛p>則將編輯指令跳至 : label 處執行。
w 寫資料到它檔內。
x 交換 hold space 與 pattern space 內容。
y 轉換(transform)字元。
雖然 , sed 只有上表所述幾個擁有基本編輯功能的函數 , 但由指令中位址參數和指令與指令間的配合 , 也能使sed 完成大部份的編輯任務。
2,1 刪除
(1) sed -e '1d' inputfile (刪除第一行)
那麼刪除第x行呢?刪除第x1,x2,x3行呢?
sed -e 'xd' inputfile
sed -e 'x1d' -e 'x2d' -e 'x3d' inputfile
當然也許還有更好的辦法。
(2) sed -e '1,3d' file (刪除第一到第三行)
思考:刪除第n行到第m行?也就是
sed -e 'n,md' file
刪除第一行到最後一行
sed -e '1,$d' file #$ 最後一行和一行的最後
(3) sed -e '/#/d' file (刪除含有'#'號的行)
思考:刪除含有字母xx的行
sed -e '/xx/d' file
思考: 刪除除含有字符串xx的所有行
sed -e '/xx/!d' file
(4) sed -e '/word1/, /word2/d' file (刪除從含有單詞word1到含有單詞word2的行)
sed -e '10,/word1/d' file
刪除文件中從第10行到含有word1的行
sed -e '/word1/,10/d' file
和上面的匹配相反,刪除從含有word1的行到第10行
(5) sed -e '/t.*t/d' file (刪除含有兩個t的行)
思考:刪除含有指定正在表達式匹配的行。
2.2 替換
Sed 可替換文件中的字串、資料行、甚至資料區。其中,表示替換字串的指令中的函數參數爲s;表示替換資料行、或資料區>的指令中的函數參數爲c。上述情況以下面三個例子說明。
*行的替換
(1) sed -e '1c/#!/bin/more' file (把第一行替換成#!/bin/more)
思考: 把第n行替換成just do it
sed -e 'nc/just do it' file
(2) sed -e '1,10c/I can do it' file (把1到10行替換成一行:I can do it)
思考: 換成兩行(I can do it! Let's start)
sed -e '1,10c/I can do it!/nLet'"/'"'s start' file
*字符的替換
(3) sed -e 's/word1/& word2/' file (將每一行的word1單詞替換成s參數最多與兩個位置參數相結合,函數參數s中有兩個特殊的符號:
& : 代表pattern
/n : 代表 pattern 中被第 n 個 /( 、/)(參照[附錄 A]) 所括起來的字串。例如
sed -e 's/w1/& w2/' file # w1的地方輸出 w1 w2
sed -e 's//(test/) /(my/) /(car/)/[/2 /3 /1]/' file #結果: [my car test]
*flag 參數舉例
sed -e 's/w1/& w2/g' file
g : 代表替換所有匹配項目;這裏,文件中所有字符串w1都會被替換成字串w1 w2
sed -e 's/w1/& w2/10' file
m(10) : 替換行內第m個符合的字串; 記住,是行內的第m個匹配的字串
sed -e 's/w1/& w2/p' file
p : 替換第一個和w1匹配的字符串爲w1 w2,並輸出到標準輸出.
sed -e 's/w1/& w2/w w2file' file
w filename : 該參數會將替換過的內容寫入到文件w2file並輸出替換後的整個文件。注意w2file裏寫的只是替換過的行。 sed 'e 's/w1/& w2/' file
這裏的flag 爲空, 這樣就只是將第一個w1匹配的字符串替換成w1 w2而後面的不進行替換。
*位置參數應用舉例
sed -e '/machine/s/phi/beta/g' file
將文件中含"machine"字串的資料行中的"phi"字串,替換成爲"beta"字串
sed -e '1,10 s/w1/& w2/g' file
把1到10內的w1字符串替換成w1 w2字符串。
sed -e '1,/else/ s/w1/& w2/g' file
把1到字符串else內的w1字符串替換成w1 w2字符串。
其它位置參數的應用與前面的相同。
2.3 內容的插入
i
基本格式:
[address] i/ 插入內容 filename
word2)
說明:
函數參數 s 表示替換(substitute)文件內字串。其指令格式如下 :
[address1[ ,address2]] s/pattern/replacemen/[flag]
sed -e '/#/i/words' file #在#字符的前面插入一行words
說明:
這裏的函數參數是i,它只能有一個地址參數。
sed -e '1/i/words' file
在第一行前加一行words
cat "word" | sed -e '/$/.doc/g' #輸出word.doc
在word後面加上後綴名,從而輸出word.doc
i 參數正好與a參數相反,它是插入到所給內容的前面.
a
a參數的使用格式如下:
[address] a/ <插入內容> filename
sed -e '/unix/a/ haha' test.txt #在含有unix的行後添加"haha"
#輸出結果爲:
unix
haha
另外: sed -e '1 a/ hh' test.txt #在第一行後添加hh字符.
2.4 文本的打印: p
基本格式:
[address1,[address2]] p
(1) sed -e '/then/ p' filename #打印所有行並重復打印含有then 的行
(2) sed -n '/then/ p' filename #只打印含有then的行
(3) sed -e '1,3 p' filename # 打印所有行並重復1-3行
(4) sed -n '1,3 p' filename # 打印1-3行
(5) sed -n '/if/,/fi/ p' filename #打印字符if和fi之間的內容
p函數爲sed的打印函數,在這裏要注意-e 和-n 參數的區別。一般使用-n參數。
2.5 字元的替換: y
例如:
(1)sed -e 'y/abc../xyz../' filename
把文件中的a字母替換成x, b替換成y, c替換成z。
(2) sed -e 'y/abc/ABC' filename
把小寫的abc轉換成大寫的ABC
2.6 反相執行命令 : !
基本格式:
[address1[ , address2]] ! 函數參數
sed -e '/1996/!d' filename
刪除除了含有1996的所有行。
2.7 改變文件中的資料: c
基本格式:
[address1[ ,address2]]c/ filename
函數參數 c 緊接着 "/" 字元用來表示此行結束 , 使用者所輸入的資料必須從下一行輸入。如果資料超過一行 , 則須在>每行的結尾加入"/"
sed -e '/zhengxh/c hhhh' filename
表示把含有字符串zhengxh的行,該成hhhh。
2.8 讀入下一行資料: n
基本格式:
[address1[ ,address2]] n
sed -n -e '/echo/n' -e 'p' temp
表示輸出文件,但如果一行含有字符串echo,則輸出包含該字符串的下一行。
sed -n -e 'n' -e 'p' filename
輸出文中的偶數行
3, 命令的複用
一次執行多個命令的方式有三種:
(1) sed 's/w1/& w2/g; 1/i/words' filename (使用;號把命令隔開,注意前面不加-e參數)
(2) sed -e 'cmd1' -e 'cmd2' filename (使用多個-e參數)
Linux awk的用法
簡介
awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤爲強大。簡單來說awk就是把文件逐行的讀入,以空格爲默認分隔符將每行切片,切開的部分再進行各種分析處理。
awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。
awk其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有自己的語言: AWK 程序設計語言 , 三位創建者已將它正式定義爲“樣式掃描和處理語言”。它允許您創建簡短的程序,這些程序讀取輸入文件、爲數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其他的功能。
使用方法
awk '{pattern + action}' {filenames}
儘管操作可能會很複雜,但語法總是這樣,其中 pattern 表示 AWK 在數據中查找的內容,而 action 是在找到匹配內容時所執行的一系列命令。花括號({})不需要在程序中始終出現,但它們用於根據特定的模式對一系列指令進行分組。 pattern就是要表示的正則表達式,用斜槓括起來。
awk語言的最基本功能是在文件或者字符串中基於指定規則瀏覽和抽取信息,awk抽取信息後,才能進行其他文本操作。完整的awk腳本通常用來格式化文本文件中的信息。
通常,awk是以文件的一行爲處理單位的。awk每接收文件的一行,然後執行相應的命令,來處理文本。
調用awk
有三種方式調用awk
1.命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的文件。
在awk中,文件的每一行中,由域分隔符分開的每一項稱爲一個域。通常,在不指名-F域分隔符的情況下,默認的域分隔符是空格。
2.shell腳本方式
將所有的awk命令插入一個文件,並使awk程序可執行,然後awk命令解釋器作爲腳本的首行,一遍通過鍵入腳本名稱來調用。
相當於shell腳本首行的:#!/bin/sh
可以換成:#!/bin/awk
3.將所有的awk命令插入一個單獨文件,然後調用:
awk -f awk-script-file input-file(s)
其中,-f選項加載awk-script-file中的awk腳本,input-file(s)跟上面的是一樣的。
本章重點介紹命令行方式。
入門實例
假設last -n 5的輸出如下
[root@www ~]# last -n 5 <==僅取出前五行
root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in
root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)
root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48)
dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00)
root tty1 Fri Sep 5 14:09 - 14:10 (00:01)
如果只是顯示最近登錄的5個帳號
#last -n 5 | awk '{print $1}'
root
root
root
dmtsai
root
awk工作流程是這樣的:讀入有'\n'換行符分割的一條記錄,然後將記錄按指定的域分隔符劃分域,填充域,$0則表示所有域,$1表示第一個域,$n表示第n個域。默認域分隔符是"空白鍵" 或 "[tab]鍵",所以$1表示登錄用戶,$3表示登錄用戶ip,以此類推。
如果只是顯示/etc/passwd的賬戶
#cat /etc/passwd |awk -F ':' '{print $1}'
root
daemon
bin
sys
這種是awk+action的示例,每行都會執行action{print $1}。
-F指定域分隔符爲':'。
如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以tab鍵分割
#cat /etc/passwd |awk -F ':' '{print $1"\t"$7}'
root /bin/bash
daemon /bin/sh
bin /bin/sh
sys /bin/sh
如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以逗號分割,而且在所有行添加列名name,shell,在最後一行添加"blue,/bin/nosh"。
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh
awk工作流程是這樣的:先執行BEGING,然後讀取文件,讀入有/n換行符分割的一條記錄,然後將記錄按指定的域分隔符劃分域,填充域,$0則表示所有域,$1表示第一個域,$n表示第n個域,隨後開始執行模式所對應的動作action。接着開始讀入第二條記錄······直到所有的記錄都讀完,最後執行END操作。
搜索/etc/passwd有root關鍵字的所有行
#awk -F: '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
這種是pattern的使用示例,匹配了pattern(這裏是root)的行纔會執行action(沒有指定action,默認輸出每行的內容)。
搜索支持正則,例如找root開頭的: awk -F: '/^root/' /etc/passwd
搜索/etc/passwd有root關鍵字的所有行,並顯示對應的shell
# awk -F: '/root/{print $7}' /etc/passwd
/bin/bash
這裏指定了action{print $7}
awk內置變量
awk有許多內置變量用來設置環境信息,這些變量可以被改變,下面給出了最常用的一些變量。
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 支持隊列中系統環境變量的使用
FILENAME awk瀏覽的文件名
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,等價於命令行 -F選項
NF 瀏覽記錄的域的個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
此外,$0變量是指整條記錄。$1表示當前行的第一個域,$2表示當前行的第二個域,......以此類推。
統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:
#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
使用printf替代print,可以讓代碼更加簡潔,易讀
awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
print和printf
awk中同時提供了print和printf兩種打印輸出的函數。
其中print函數的參數可以是變量、數值或者字符串。字符串必須用雙引號引用,參數用逗號分隔。如果沒有逗號,參數就串聯在一起而無法區分。這裏,逗號的作用與輸出文件的分隔符的作用是一樣的,只是後者是空格而已。
printf函數,其用法和c語言中printf基本相似,可以格式化字符串,輸出複雜時,printf更加好用,代碼更易懂。
awk編程
變量和賦值
除了awk的內置變量,awk還可以自定義變量。
下面統計/etc/passwd的賬戶人數
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd root:x:0:0:root:/root:/bin/bash ...... user count is 40
count是自定義變量。之前的action{}裏都是隻有一個print,其實print只是一個語句,而action{}可以有多個語句,以;號隔開。
這裏沒有初始化count,雖然默認是0,但是妥當的做法還是初始化爲0:
awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
[start]user count is 0
root:x:0:0:root:/root:/bin/bash
...
[end]user count is 40
統計某個文件夾下的文件佔用的字節數
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}' [end]size is 8657198
如果以M爲單位顯示:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.25889 M
注意,統計不包括文件夾的子目錄。
條件語句
awk中的條件語句是從C語言中借鑑來的,見如下聲明方式:
if (expression) { statement; statement; ... ... } if (expression) { statement; } else { statement2; } if (expression) { statement1; } else if (expression1) { statement2; } else { statement3; }
統計某個文件夾下的文件佔用的字節數,過濾4096大小的文件(一般都是文件夾):
ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.22339 M
循環語句
awk中的循環語句同樣借鑑於C語言,支持while、do/while、for、break、continue,這些關鍵字的語義和C語言中的語義完全相同。
數組
因爲awk中數組的下標可以是數字和字母,數組的下標通常被稱爲關鍵字(key)。值和關鍵字都存儲在內部的一張針對key/value應用hash的表格裏。由於hash不是順序存儲,因此在顯示數組內容時會發現,它們並不是按照你預料的順序顯示出來的。數組和變量一樣,都是在使用時自動創建的,awk也同樣會自動判斷其存儲的是數字還是字符串。一般而言,awk中的數組用來從記錄中收集信息,可以用於計算總和、統計單詞以及跟蹤模板被匹配的次數等等。
顯示/etc/passwd的賬戶
awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
1 daemon
2 bin
3 sys
4 sync
5 games
......
這裏使用for循環遍歷數組