0x00 前言
終于!終于!終于!時隔多年后,終于要認真學一次了!
先放正則相關的圖,留存查詢




另外一定要注意:語系編碼對正則同樣是有影響的!
三劍客的功能非常強大,但我們只需要掌握他們分別擅長的領域即可
grep擅長查找功能sed擅長取行和替換awk擅長取列
0x01 grep
grep是日常用的最多的也是最熟悉的了
[root@localhost ~]grep --help
Usage: grep [OPTION]... PATTERN [FILE]...
Search for PATTERN in each FILE or standard input.
PATTERN is, by default, a basic regular expression (BRE).
Example: grep -i 'hello world' menu.h main.c
Regexp selection and interpretation:
-E, --extended-regexp PATTERN is an extended regular expression (ERE)
-F, --fixed-strings PATTERN is a set of newline-separated fixed strings
-G, --basic-regexp PATTERN is a basic regular expression (BRE)
-P, --perl-regexp PATTERN is a Perl regular expression
-e, --regexp=PATTERN use PATTERN for matching
-f, --file=FILE obtain PATTERN from FILE
-i, --ignore-case ignore case distinctions
-w, --word-regexp force PATTERN to match only whole words
-x, --line-regexp force PATTERN to match only whole lines
-z, --null-data a data line ends in 0 byte, not newline
Miscellaneous:
-s, --no-messages suppress error messages
-v, --invert-match select non-matching lines
-V, --version display version information and exit
--help display this help text and exit
Output control:
-m, --max-count=NUM stop after NUM matches
-b, --byte-offset print the byte offset with output lines
-n, --line-number print line number with output lines
--line-buffered flush output on every line
-H, --with-filename print the file name for each match
-h, --no-filename suppress the file name prefix on output
--label=LABEL use LABEL as the standard input file name prefix
-o, --only-matching show only the part of a line matching PATTERN
-q, --quiet, --silent suppress all normal output
--binary-files=TYPE assume that binary files are TYPE;
TYPE is 'binary', 'text', or 'without-match'
-a, --text equivalent to --binary-files=text
-I equivalent to --binary-files=without-match
-d, --directories=ACTION how to handle directories;
ACTION is 'read', 'recurse', or 'skip'
-D, --devices=ACTION how to handle devices, FIFOs and sockets;
ACTION is 'read' or 'skip'
-r, --recursive like --directories=recurse
-R, --dereference-recursive
likewise, but follow all symlinks
--include=FILE_PATTERN
search only files that match FILE_PATTERN
--exclude=FILE_PATTERN
skip files and directories matching FILE_PATTERN
--exclude-from=FILE skip files matching any file pattern from FILE
--exclude-dir=PATTERN directories that match PATTERN will be skipped.
-L, --files-without-match print only names of FILEs containing no match
-l, --files-with-matches print only names of FILEs containing matches
-c, --count print only a count of matching lines per FILE
-T, --initial-tab make tabs line up (if needed)
-Z, --null print 0 byte after FILE name
Context control:
-B, --before-context=NUM print NUM lines of leading context
-A, --after-context=NUM print NUM lines of trailing context
-C, --context=NUM print NUM lines of output context
-NUM same as --context=NUM
--group-separator=SEP use SEP as a group separator
--no-group-separator use empty string as a group separator
--color[=WHEN],
--colour[=WHEN] use markers to highlight the matching strings;
WHEN is 'always', 'never', or 'auto'
-U, --binary do not strip CR characters at EOL (MSDOS/Windows)
-u, --unix-byte-offsets report offsets as if CRs were not there
(MSDOS/Windows)
'egrep' means 'grep -E'. 'fgrep' means 'grep -F'.
Direct invocation as either 'egrep' or 'fgrep' is deprecated.
When FILE is -, read standard input. With no FILE, read . if a command-line
-r is given, - otherwise. If fewer than two FILEs are given, assume -h.
Exit status is 0 if any line is selected, 1 otherwise;
if any error occurs and -q is not given, the exit status is 2.
Report bugs to: bug-grep@gnu.org
GNU Grep home page: <http://www.gnu.org/software/grep/>
General help using GNU software: <http://www.gnu.org/gethelp/>
[root@localhost ~]
grep的用法
命令還是非常多的,把重要的一個一個來試試,不加任何選項,DHCP關鍵詞,/etc/services文本檔案

不區分大小寫查找,使用-i

一定要匹配上整個單詞的查找,包含或者前后有其余單詞字符的均不匹配,使用-w

匹配注釋的空行,這里由于#是特殊符號,需要轉義,使用-x,匹配整行資料

匹配注釋的空行,并顯示這些注釋行的行號,使用-n

統計匹配注釋的空行的數量,使用-c

匹配以#開頭的行數,使用-e引數,但是只能接受一個引數的正則

匹配ARP或者DHCP關鍵字的行數,使用-E使用擴展正則,可以使用多個引數進行正則匹配

輸出沒有#號的行,使用-v

匹配前10個#開頭的行數,使用-m

顯示DHCP所在的字符數

這里將/etc/services分成兩部分,每部分6000行
[root@localhost ~]split -l 6000 /etc/services services-
[root@localhost ~]ll services-a*
-rw-r--r-- 1 root root 343604 Feb 11 15:06 services-aa
-rw-r--r-- 1 root root 326689 Feb 11 15:06 services-ab
匹配這兩個檔案中的FTP行,帶-H顯示檔案名

匹配這兩個檔案中的FTP行,帶-h不顯示檔案名

只匹配關鍵字及其出現的行數,使用-o

使用-q,查找后無任何輸出,一般用于shell內進行流程控制
[root@localhost ~]echo "if grep -q DHCP /etc/services; then echo 1; else echo 2;fi" > 1.sh && chmod 777 1.sh
[root@localhost ~]./1.sh
1
[root@localhost ~]echo "if grep -q aaaaaaaa /etc/services; then echo 1; else echo 2;fi" > 1.sh && chmod 777 1.sh
[root@localhost ~]./1.sh
2
對二進制檔案進行處理時的操作
#二進制檔案出錯
[root@localhost ~] grep abc /bin/ls
Binary file /bin/ls matches
#忽略二進制檔案
[root@localhost ~] grep -I abc /bin/ls
#以文本模式讀取二進制檔案
[root@localhost ~] grep -a abc /bin/ls
ignoring invalid value of environment variable QUOTING_STYLE: %signoring invalid width in environment variable COLUMNS: %signoring invalid tab size in environment variable TABSIZE: %sabcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1 - +FORMAT (e.g., +%H:%M) for a 'date'-style format
在目錄所有的檔案下查找DHCP,使用-r,跳過符號鏈接,如果使用-R則不跳過,

在除了http-build和lamp-build目錄外查找FROM關鍵字,使用--exclude-dir

只顯示匹配上的檔案名,使用-l,顯示沒有匹配上的檔案名使用-L

在使用-n,-H等引數時,可以使開頭加上tab,然并卵

-A是顯示匹配后和它后面的n行

-B是顯示匹配行和它前面的n行

-C是匹配行和它前后各n行

在使用了-A -B -C的查尋結果后增加分隔符,使用--group-separator

還有一些感覺不太常用的方法,比如-z、-Z,-u、-U等都找不到合適的例子來演示,但是我感覺到這grep已經夠用了!
0x02 sed
命令沒有grep多,但是用于替換和進行行數的操作很方便
[root@localhost ~]sed --help
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...
-n, --quiet, --silent
suppress automatic printing of pattern space
-e script, --expression=script
add the script to the commands to be executed
-f script-file, --file=script-file
add the contents of script-file to the commands to be executed
--follow-symlinks
follow symlinks when processing in place
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if SUFFIX supplied)
-c, --copy
use copy instead of rename when shuffling files in -i mode
-b, --binary
does nothing; for compatibility with WIN32/CYGWIN/MSDOS/EMX (
open files in binary mode (CR+LFs are not treated specially))
-l N, --line-length=N
specify the desired line-wrap length for the `l' command
--posix
disable all GNU extensions.
-r, --regexp-extended
use extended regular expressions in the script.
-s, --separate
consider files as separate rather than as a single continuous
long stream.
-u, --unbuffered
load minimal amounts of data from the input files and flush
the output buffers more often
-z, --null-data
separate lines by NUL characters
--help
display this help and exit
--version
output version information and exit
除此之外在man grep中還可以找到一些常見的方法,詳細用法看示例
a,在下面增加i,在上面增加d,洗掉c,整行修改s,部分修改p,列印y,單字替換w,將內容寫入新檔案r,將新檔案插入原檔案q,匹配退出
sed的用法
先用最常見的-e,拷貝/etc/passwd的前五行到本目錄下形成檔案passwd
在第二行下面增加資料
[root@localhost ~]cat passwd | sed -e '2a test!'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
test!
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
在第二行上面增加資料
[root@localhost ~]cat passwd | sed -e '2i test!'
root:x:0:0:root:/root:/bin/bash
test!
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
在第二行下面增加兩行資料
[root@localhost ~]cat passwd | sed -e '2a test test \
> haha haha'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
test test
haha haha
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
將第二行換成*****
[root@localhost ~]cat passwd |sed -e '2c *********'
root:x:0:0:root:/root:/bin/bash
*********
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
洗掉第三行到最后一行
[root@localhost ~]cat passwd |sed -e '3,$d'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
將所有的o換成大寫的O
[root@localhost ~]cat passwd |sed -e 's/o/O/g'
rOOt:x:0:0:rOOt:/rOOt:/bin/bash
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
將第二行的o換成大寫的O
[root@localhost ~]cat passwd |sed -e '2s/o/O/g'
root:x:0:0:root:/root:/bin/bash
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
將第三行到第四行第一個的o換成大寫的O
[root@localhost ~]cat passwd |sed -e 's/o/O/'
rOot:x:0:0:root:/root:/bin/bash
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
將所有的數字都換成*,要注意,前后字符數量一致
[root@localhost ~]cat passwd |sed -e 'y/0123456789/**********/'
root:x:*:*:root:/root:/bin/bash
BIN:x:*:*:BIN:/BIN:/sBIN/nologin
daemon:x:*:*:daemon:/sbin:/sbin/nologin
adm:x:*:*:adm:/var/adm:/sbin/nologin
lp:x:*:*:lp:/var/spool/lpd:/sbin/nologin
在第二行插入分隔符檔案
[root@localhost ~]cat a.txt
**********
[root@localhost ~]cat passwd |sed -e "2r a.txt"
root:x:0:0:root:/root:/bin/bash
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
查尋到關鍵字就退出
[root@localhost ~]cat passwd |sed -e '/nologin/q'
root:x:0:0:root:/root:/bin/bash
BIN:x:1:1:BIN:/BIN:/sBIN/nologin
-n選項為安靜模式,一般和p方法一起用,列印出2-3行
[root@localhost ~]cat passwd |sed -n '2,3p'
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
將2-3行資料寫入新檔案,配合-n選項效果更好
[root@localhost ~]cat passwd |sed -n '2,3w test.txt'
[root@localhost ~]cat test.txt
BIN:x:1:1:BIN:/BIN:/sBIN/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
比如可以利用正則來獲取IP地址
[root@localhost ~]ifconfig ens32|sed -n '2p'|sed -e 's/ *inet //'|sed -e 's/ *netmask.*//'
10.1.1.222
如果用的-i選項,則是不輸出結果,直接修改原檔案,使用的時候一定要注意
[root@localhost ~]cat passwd
root:x:0:0:root:/root:/bin/bash
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
[root@localhost ~]sed -i '2s/bin/BIN/g' passwd ;cat passwd
root:x:0:0:root:/root:/bin/bash
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
sed命令的尋址
前面在介紹各個腳本命令時,我們一直忽略了對 address部分的介紹,對各個腳本命令來說,address用來表明該腳本命令作用到文本中的具體行,通過之前的顯示應該有一定感覺了,再來總結下,
默認情況下,sed 命令會作用于文本資料的所有行,如果只想將命令作用于特定行或某些行,則必須寫明 address 部分,表示的方法有以下 2 種:
- 以數字形式指定行區間;
- 用文本模式指定具體行區間,
以上兩種形式都可以使用如下這 2 種格式,分別是:
[address]腳本命令
或者
address {
多個腳本命令
}
以數字形式指定行區間
```bash
[root@localhost ~]cat passwd |sed -n '2,3p'
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
以文本指定區間
[root@localhost ~]cat passwd |sed -n '/root/p'
root:x:0:0:root:/root:/bin/bash
使用多腳本命令把所有的uid前后都加上",gid前后加上',這里使用-f選項,呼叫腳本檔案更方便
[root@localhost ~]cat sed.sh
/[0-9]/{
s//\"&\"/1
s//\'&\'/2
}
[root@localhost ~]cat passwd |sed -f sed.sh
root:x:"0":'0':root:/root:/bin/bash
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
sed的多行處理
N命令會將下一行文本內容添加到緩沖區已有資料之后(之間用換行符分隔),從而使前后兩個文本行同時位于緩沖區中,sed 命令會將這兩行資料當成一行來處理,
[root@localhost ~] cat data2.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~] sed '/first/{ N ; s/\n/ / }' data2.txt
This is the header line.
This is the first data line. This is the second data line.
This is the last line.
D 命令將緩沖區中第一個換行符(包括換行符)之前的內容洗掉掉,
[root@localhost ~]head -n 10 /etc/services | sed -e 's/\#//g' > services
[root@localhost ~]cat services
/etc/services:
$Id: services,v 1.55 2013/04/14 ovasik Exp $
Network services, Internet style
IANA services version: last updated 2013-04-10
Note that it is presently the policy of IANA to assign a single well-known
port number for both TCP and UDP; hence, most entries here have two entries
even if the protocol doesn't support UDP operations.
Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
洗掉匹配的第一個空白行,先匹配空行,然后使用N指定將下一行也加入緩沖區,然后利用下一行的Net關鍵字進行匹配洗掉匹配上的第一個換行符及之前的內容,
[root@localhost ~]cat services | sed -e '/^$/{N;/Net/D}'
/etc/services:
$Id: services,v 1.55 2013/04/14 ovasik Exp $
Network services, Internet style
IANA services version: last updated 2013-04-10
Note that it is presently the policy of IANA to assign a single well-known
port number for both TCP and UDP; hence, most entries here have two entries
even if the protocol doesn't support UDP operations.
Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
P命令列印多行資料,還是利用上面的例子,p會輸出匹配上的內容,而P只輸出匹配上內容當中的第一個換行符及之前的內容
[root@localhost ~]cat services | sed -n '/^$/{N;/Net/p}'
Network services, Internet style
[root@localhost ~]cat services | sed -n '/^$/{N;/Net/P}'
[root@localhost ~]
sed保持空間
相關的命令有5條
h將模式空間中的內容復制到保持空間H將模式空間中的內容附加到保持空間g將保持空間中的內容復制到模式空間G將保持空間中的內容附加到模式空間x交換模式空間和保持空間中的內容
通常,在使用 h 或 H 命令將字串移動到保持空間后,最侄訓要用 g、G 或 x 命令將保存的字串移回模式空間,保持空間最直接的作用是,一旦我們將模式空間中所有的檔案復制到保持空間中,就可以清空模式空間來加載其他要處理的文本內容,
由于有兩個緩沖區域,下面的例子中演示了如何用 h 和 g 命令來將資料在 sed 緩沖區之間移動,
[root@localhost ~]# cat data2.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed -n '/first/ {h ; p ; n ; p ; g ; p }' data2.txt
This is the first data line.
This is the second data line.
This is the first data line.
這個例子的運行程序是這樣的:
- sed腳本命令用正則運算式過濾出含有單詞first的行;
- 當含有單詞 first 的行出現時,h 命令將該行放到保持空間;
- p 命令列印模式空間也就是第一個資料行的內容;
- n 命令提取資料流中的下一行(This is the second data line),并將它放到模式空間;
- p 命令列印模式空間的內容,現在是第二個資料行;
- g 命令將保持空間的內容(This is the first data line)放回模式空間,替換當前文本;
- p 命令列印模式空間的當前內容,現在變回第一個資料行了,
講道理,還沒完全理解這個可以怎么high,留待將來
sed分支
通常,sed程式的執行程序會從第一個腳本命令開始,一直執行到最后一個腳本命令,sed 提供了 b 分支命令來改變命令腳本的執行流程,其結果與結構化編程類似,
b分支命令基本格式為:
[address]b [label]
其中,address 引數決定了哪些行的資料會觸發分支命令,label 引數定義了要跳轉到的位置,
#原檔案
[root@localhost ~]cat services
/etc/services:
$Id: services,v 1.55 2013/04/14 ovasik Exp $
Network services, Internet style
IANA services version: last updated 2013-04-10
Note that it is presently the policy of IANA to assign a single well-known
port number for both TCP and UDP; hence, most entries here have two entries
even if the protocol doesnt support UDP operations.
Updated from RFC 1700, ''Assigned Numbers'' (October 1994). Not all ports
#將原檔案中的services改為Services,但是當遇到Network時,就改為SERvices
[root@localhost ~]cat services | sed -e '{/Net/b jump;s/ser/Ser/g
> :jump
> s/ser/SER/g}'
/etc/Services:
$Id: Services,v 1.55 2013/04/14 ovasik Exp $
Network SERvices, Internet style
IANA Services version: last updated 2013-04-10
Note that it is presently the policy of IANA to assign a single well-known
port number for both TCP and UDP; hence, most entries here have two entries
even if the protocol doesnt support UDP operations.
Updated from RFC 1700, ''Assigned Numbers'' (October 1994). Not all ports
#如果上述看起來吃力就寫成腳本
[root@localhost ~]cat services | sed -f sed.sh
/etc/Services:
$Id: Services,v 1.55 2013/04/14 ovasik Exp $
Network SERvices, Internet style
IANA Services version: last updated 2013-04-10
Note that it is presently the policy of IANA to assign a single well-known
port number for both TCP and UDP; hence, most entries here have two entries
even if the protocol doesn't support UDP operations.
Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
[root@localhost ~]cat sed.sh
{/Net/b jump;s/ser/Ser/g
:jump
s/ser/SER/g
}
其實就像編程中的判斷陳述句,當匹配上了條件,就跳過前面的陳述句,執行后面的陳述句,
當然除了向后跳,還可以像前跳,用于回圈處理,比如替換所有的符號為*,
[root@localhost ~]cat services | sed -e '{/[[:punct:]]/b start;
>:start
>s/[[:punct:]]/\*/g}'
*etc*services*
*Id* services*v 1*55 2013*04*14 ovasik Exp *
Network services* Internet style
IANA services version* last updated 2013*04*10
Note that it is presently the policy of IANA to assign a single well*known
port number for both TCP and UDP* hence* most entries here have two entries
even if the protocol doesn*t support UDP operations*
Updated from RFC 1700* **Assigned Numbers** *October 1994** Not all ports
但是需要注入,如果b沒有指定label則會直接跳到最后,下方中要講的t命令也是如此,
t類似于 b 分支命令,t 命令也可以用來改變 sed 腳本的執行流程,
t 測驗命令會根據 s 替換命令的結果,如果匹配并替換成功,則腳本的執行會跳轉到指定的標簽;反之,t 命令無效,
#將所有的數字換成*
[root@localhost ~]cat services | sed -e '{
> :start
> s/[[:digit:]]/\*/
> t start}'
/etc/services:
$Id: services,v *.** ****/**/** ovasik Exp $
Network services, Internet style
IANA services version: last updated ****-**-**
Note that it is presently the policy of IANA to assign a single well-known
port number for both TCP and UDP; hence, most entries here have two entries
even if the protocol doesn't support UDP operations.
Updated from RFC ****, ``Assigned Numbers'' (October ****). Not all ports
0x03 awk
感覺是一個比一個復雜,頭痛!
awk主要是用于處理列的資料,查看help確實不多,但是看了下man,恐怖如斯
[root@localhost ~]awk --help
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-N --use-lc-numeric
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version
To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.
gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.
Examples:
gawk '{ sum += $1 }; END { print sum }' file
gawk -F: '{ print $1 }' /etc/passwd
awk命令的基本格式為:
awk [選項] '腳本命令' 檔案名
選項就三個,還挺好理解
-Ffs ,指定以 fs 作為輸入行的分隔符,awk 命令默認分隔符為空格或制表符,-ffile,從腳本檔案中讀取 awk 腳本指令,以取代直接在命令列中輸入指令,-vvar=val,在執行處理程序之前,設定一個變數 var,并給其設備初始值為 val,
關鍵還是得在于腳本命令,由兩部分組成,用起來和sed還是非常接近的
'匹配規則{執行命令}'
先看一個簡單的案例
[root@localhost ~]cat services
/etc/services:
$Id: services,v 1.55 2013/04/14 ovasik Exp $
Network services, Internet style
IANA services version: last updated 2013-04-10
Note that it is presently the policy of IANA to assign a single well-known
port number for both TCP and UDP; hence, most entries here have two entries
even if the protocol doesnt support UDP operations.
Updated from RFC 1700, ''Assigned Numbers'' (October 1994). Not all ports
#輸出兩個空行所對應的字母
[root@localhost ~]cat services | awk '/^$/{print "bbbbbbbb"}'
bbbbbbbb
bbbbbbbb
awk的用法
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
- 第一步:運行
BEGIN{ commands }陳述句塊中的陳述句, - 第二步:從檔案或標準輸入
(stdin)讀取一行,然后運行pattern{ commands }陳述句塊,它逐行掃描檔案,從第一行到最后一行反復這個程序,直到檔案所有被讀取完成, - 第三步:當讀至輸入流末尾時,運行
END{ commands }陳述句塊,
BEGIN陳述句塊在awk開始從輸入流中讀取行之前被運行,這是一個可選的陳述句塊,比方變數初始化、列印輸出表格的表頭等陳述句通常能夠寫在BEGIN陳述句塊中,
END陳述句塊在awk從輸入流中讀取全然部的行之后即被運行,比方列印全部行的分析結果這類資訊匯總都是在END陳述句塊中完畢,它也是一個可選陳述句塊,
pattern陳述句塊中的通用命令是最重要的部分,它也是可選的,假設沒有提供pattern陳述句塊,則默認運行{ print },即列印每個讀取到的行,awk讀取的每一行都會運行該陳述句塊,
這三個部分缺少任何一部分都可以,
接下來看個例子
[root@localhost ~]ll
total 56
-rw-r--r-- 1 root root 8 Feb 10 20:44 -
-rwxrwxrwx 1 root root 63 Feb 11 15:29 1.sh
-rw-r--r-- 1 root root 3 Feb 10 21:17 1.txt
-rw-r--r-- 1 root root 53 Feb 10 20:34 2.txt
-rw-------. 1 root root 1333 Jan 31 23:26 anaconda-ks.cfg
-rw-r--r-- 1 root root 11 Feb 12 11:01 a.txt
-rw-r--r-- 1 root root 274 Feb 9 15:04 Dockerfile
drwxr-xr-x 2 root root 24 Feb 8 20:20 http-build
drwxr-xr-x 2 root root 24 Feb 9 19:54 lamp-build
-rw-r--r-- 1 root root 183 Feb 12 10:42 passwd
-rw-r--r-- 1 root root 36 Feb 12 16:36 sed.sh
-rw-r--r-- 1 root root 429 Feb 12 15:04 services
-rw-r--r-- 1 root root 10240 Feb 10 21:28 test.tar
-rw-r--r-- 1 root root 73 Feb 12 10:58 test.txt
[root@localhost ~]ll | awk '{print $1}'
total
-rw-r--r--
-rwxrwxrwx
-rw-r--r--
-rw-r--r--
-rw-------.
-rw-r--r--
-rw-r--r--
drwxr-xr-x
drwxr-xr-x
-rw-r--r--
-rw-r--r--
-rw-r--r--
-rw-r--r--
-rw-r--r--
在這里awk后面沒有BEGIN和END,跟著的是pattern,也就是每一行都會經過這個命令,在awk中$n,表示第幾列,在這里表示列印每一行的第一列,
$0當前記錄(這個變數中存放著整個行的內容)$1~$n當前記錄的第n個欄位,欄位間由FS分隔FS輸入欄位分隔符 默認是空格或TabNF當前記錄中的欄位個數,就是有多少列NR已經讀出的記錄數,就是行號,從1開始,如果有多個檔案話,這個值也是不斷累加中,FNR當前記錄數,與NR不同的是,這個值會是各個檔案自己的行號RS輸入的記錄分隔符, 默認為換行符OFS輸出欄位分隔符, 默認也是空格ORS輸出的記錄分隔符,默認為換行符FILENAME當前輸入檔案的名字
列印每一行的行數
[root@localhost ~]ll | awk '{print NR "\t" $1}'
1 total
2 -rw-r--r--
3 -rwxrwxrwx
4 -rw-r--r--
5 -rw-r--r--
6 -rw-------.
7 -rw-r--r--
8 -rw-r--r--
9 drwxr-xr-x
10 drwxr-xr-x
11 -rw-r--r--
12 -rw-r--r--
13 -rw-r--r--
14 -rw-r--r--
15 -rw-r--r--
再來看一下格式化輸出
[root@localhost ~]awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$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:bin:x:1:1:bin:/bin:/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin
filename:/etc/passwd,linenumber:4,columns:7,linecontent:adm:x:3:4:adm:/var/adm:/sbin/nologin
filename:/etc/passwd,linenumber:5,columns:7,linecontent:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
filename:/etc/passwd,linenumber:6,columns:7,linecontent:sync:x:5:0:sync:/sbin:/bin/sync
filename:/etc/passwd,linenumber:7,columns:7,linecontent:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
filename:/etc/passwd,linenumber:8,columns:7,linecontent:halt:x:7:0:halt:/sbin:/sbin/halt
filename:/etc/passwd,linenumber:9,columns:7,linecontent:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
filename:/etc/passwd,linenumber:10,columns:7,linecontent:operator:x:11:0:operator:/root:/sbin/nologin
filename:/etc/passwd,linenumber:11,columns:7,linecontent:games:x:12:100:games:/usr/games:/sbin/nologin
filename:/etc/passwd,linenumber:12,columns:7,linecontent:ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
filename:/etc/passwd,linenumber:13,columns:7,linecontent:nobody:x:99:99:Nobody:/:/sbin/nologin
filename:/etc/passwd,linenumber:14,columns:7,linecontent:systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
filename:/etc/passwd,linenumber:15,columns:7,linecontent:dbus:x:81:81:System message bus:/:/sbin/nologin
filename:/etc/passwd,linenumber:16,columns:7,linecontent:polkitd:x:999:998:User for polkitd:/:/sbin/nologin
filename:/etc/passwd,linenumber:17,columns:7,linecontent:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
filename:/etc/passwd,linenumber:18,columns:7,linecontent:postfix:x:89:89::/var/spool/postfix:/sbin/nologin
filename:/etc/passwd,linenumber:19,columns:7,linecontent:apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
awk也可以使用語法,比如if、while等都是借鑒于C語言,,,比如選擇出/etc/passwd中uid小于5的用戶名及uid
[root@localhost ~]cat /etc/passwd | awk -F ":" '$3<5 {print $1 "\t" $3}'
root 0
bin 1
daemon 2
adm 3
lp 4
比如可以借用變數,用來計算1到100的和
[root@localhost ~] awk 'BEGIN{for(i=1;i<=100;i++){test+=i}print test}'
5050
實在是太狠了,慢慢來吧,以后在實戰中體會,嘿嘿,
最后再用awk獲取ip地址,在處理資料上感覺比sed好用多了,強大!
[root@localhost ~]ifconfig ens32|awk '/inet /{print $2}'
10.1.1.222
最后,用大年三十和年初一完成的長篇攻略,祝大家牛年大吉,牛氣沖天!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/259153.html
標籤:其他
