sed與awk

ftp://ftp.oreilly.com/published/oreilly/nutshell/sedawk_2

 有3種方法能夠在命令行上放多個指令:html

1. 用分號分隔指令
sed 's/ma/, mutil/;s/zhao/zzzz/'
2, 使用-e
sed -e 's/fs/fsgf/' -e 's/dfdg/dhs/'
3. 使用分行指令功能
    sed '
s/g/dfgh/
s/zz/dfgf/
s/CA/,FG/' list

4. sed / awk -f scriptfile file

sed和awk指令結構相同,都是由模式和過程組成,而且都可使用多個指令。在awk中語句和函數取代了一個或兩個字符組成的命令序列,例如print語句打印輸出。linux

 awk出錯信息git

1. 沒有用大括號{},將動做括起來。
2. 沒有用單引號' '將指令括起來。
3. 沒有用斜槓//將正則括起來。

 awk引用外部變量http://www.xuebuyuan.com/105422.html正則表達式

awk在使用某個變量前沒必要先賦值,由於awk將變量複製爲空字符串。shell

正則相關編程

1. 在awk中點號.能夠匹配換行。
2. [...]方括號中^表示取反,即取其餘字符,awk中包括換行。第一個字符爲右括號]或-時表示它是成員,同事存在時]放第一個,-放最後。其餘元字符在方括號中失去原來的含義,反斜槓\在awk的方括號中仍有特殊意義,能夠轉義連字符或方括號,如[a\]1]。
3. {n,m}在有些awk中仍然不能使用。awk支持egrep中的大多數正則用法。擴展正則:+, *, |, (), {},
4. .[!?;:,".] . 第一個和最後一個點是通配。
5.
POSIX字符類及意義:  必須出如今方括號表達式中,如[[:upper:]]
[:upper:]  表示大寫字母[A~Z]
[:lower:]  表示小寫字母[a~z]
[:digit:]  表示阿拉伯數字[0~9]
[:alnum:]  表示大小寫字母和阿拉伯數字[A~Za~z0~9]
[:space:]  表示任何產生空白的字符,包括空格或Tab鍵等
[:alpha:]  表示大小寫字母[A~Za~z]
[:cntrl:]  表示鍵盤的控制按鍵,包括Tab、Del等按鍵
[:graph:]  表示除了空格符(空格鍵與Tab鍵)外的其餘全部按鍵
[:print:]  表示任何能夠被打印出來的字符
[:xdigit:] 表示十六進制數字[0~9A~Za~z]
[:blank:]  表示空格鍵與Tab鍵
[:punct:]  表示標點符號,包括:" ' ? ! ; : # $... 
基本sed命令
sed命令能夠指定0個,1個,或2個地址。每一個地址都是一個描述模式,行號或者正則表達式。 注: 行號計數器不會由於多個輸入文件重置。 若是指定了逗號分隔的兩個地址,那麼命令應用於第一個地址的第一行和它後面的行,直到匹配第二個地址的行(包括此行)。第二個地址從第一個地址以後開始尋找。第一個地址啓用動做,第二個地址禁用動做,沒法先行決定第二個地址是否會匹配,一旦匹配了第一個地址,這個動做就應用與這些行。直至第二個地址匹配。 若是地址後有感嘆號
!,那麼命令將應用與不匹配該地址的全部行。 /^\.TS/,/^\.Te/!d 刪除這些行以外的全部行。

$能夠表示最後一行,但不該該和正則表達式中的$混淆。正則必須封閉在斜槓(/)中。 /^$/d

命令後添加空格會產生語法錯誤,命令的結束必須在行的結尾處。
若是命令之間用分號分隔,那麼能夠講多個sed命令放在同一行。 n;d在結構上是正確的,而後在n後面放置一個空格會致使語法錯誤,而在d前面放置一個空格是能夠的。不提倡在同一行放置多個命令。
分組命令
linux sed命令詳解 http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2856901.html
http://www.cnblogs.com/stephen-liu74/archive/2011/11/17/2245130.html
sed使用大括號{}將一個地址嵌套在另外一個地址中,或者在相同的地址上引用多個命令。 若是想指定行的範圍,而後再這個範圍內再指定另外一個地址,則能夠嵌套地址。注:左大括號必須在行末,並且右大括號自己必須單獨佔一行。要確保在大括號以後沒有空格。
/^\.TS/,/^\.Te/{          注:大括號能夠在同一行上,命令之間用分號隔開。sed -n '/root/{n;d}' /etc/passwd #將匹配root行的下一行刪除
/^$/d  #命令在大括號內能夠縮進
s/zhaodfd/.ps 8/
s/^\.vs 2/.ps 10/  #替換部分的點號沒必要轉義。
}
替換
[address]s/pattern/replacement/flags
flags能夠是:n(第n次), g, p, W file(寫入文件)
分隔符能夠是任意字符,出現3次而且在replacement以後是必須的。s!/home/z!/home/x!
在replacement部分只有下列字符有特殊含義:
&:正則匹配的整個內容
\n : 第n個字符串,在pattern中用\(。。。\)指定。
\ :轉義字符。&符號,反斜槓\,定界字符,換行均可以用\轉義。所以除了正則中的元字符外,sed的替換部分也有元字符。
echo 'zh xng' | sed 's/ /\    #轉義換行,\&    注: 上換行用\n也能夠
xxxxxxxx\      #換行
yyyyyyyyyy/'
注: 若是匹配同一行的多個替換命令,那麼該行的多個備份就會被打印或者寫到文件中。
刪除
d,刪除整行,而不是匹配部分。一旦執行刪除命令,那麼在「空的」模式空間中就不會再有命令執行。刪除命令會致使讀取新的輸入行,而編輯腳本則從頭開始新的一輪(這一行爲和next命令相同),UNIX文件寫到:不容許在被刪除的行上進一步操做。
追加,插入,更改
[line-address]a\, [line-address]i\, [address]c\. 命令後面接反斜槓或者空格均可以。可是用反斜槓纔是正路,不少書籍和命令詳解都用的是反斜槓。
[root@tg output]# echo -e 'zhao xiang dsgf fsad  ssdf sdgfdfsgd' | sed '/zhao/a\ ni hao'  
#斜槓後面的任何內容追加在匹配行以後,即便是命令 /xian/i\ first line也被當作文本。空格也原樣追加。
[root@tg output]# echo -e 'zhao xiang dsgf fsad ssdf sdgfdfsgd' | sed '/zhao/a\ ni hao' zhao xiang dsgf fsad ssdf sdgfdfsgd ni hao [root@tg output]# echo -e 'zhao xiang dsgf fsad ssdf sdgfdfsgd' | sed '/zhao/a ni hao' #若是命令後面接空格,則多餘的空格被忽略了。 zhao xiang dsgf fsad ssdf sdgfdfsgd ni hao
正確的作法應該是在命令後用反斜槓,而後追加的文本單獨起一行,文本中有換行用\n或者用反斜槓換行。最後一行不用反斜槓。 這樣即便有多個命令也不會有問題。
[root@tg output]# echo 'test  zhao xiang ' | sed '/^test/a\
--->this is a example
> /xiang/i\
> first line'
first line
test  zhao xiang 
--->this is a example
[root@tg output]# 
[root@tg output]# echo 'test  zhao xiang ' | sed '/^test/i\
> '

test  zhao xiang 
[root@tg output]#插入空行,讓命令後面的行爲空
更改命令清除模式空間,與刪除命令有一樣的效果,在更改命令以後的命令不該該被提供。
插入和追加命令不影響模式空間的內容。所提供的文本將不匹配後續命令的任何地址,那些命令也不影響該文本,無論什麼更改改變了模式空間,所提供的文本仍然會正確輸出。即便模式空間不是那樣的,並且,所提供的文本不參與sed的內部計數器

 列表命令數組

列表命令l 用於顯示模式空間的內容,並將非打印字符顯示爲兩個數字的ASCII碼。相似於vi的列表命令(:l)dom

sed -n -e "l" test
由於列表命令當即產生輸出,因此抑制默認的輸出,不然會獲得行的重複。

 轉換函數

[address]y/abc/xyz/ 影響模式空間的全部內容post

打印行號

[line-address]= , 這個命令不能對一個範圍的行進行操做。

下一步

[address]n , 輸出模式空間的內容(若是沒有抑制輸出)而後讀取下一行,替換模式空間,而不返回到腳本的頂端,以前的命令應用於當前行,後續命令應用於替換以後的內容。

讀和寫

[line-address]r file, [address]w file . 讀命令將由fiel指定的文件肯定的行以後的內容讀入模式空間,不能對行範圍操做。寫命令將模式空間的內容寫入文件。文件名以前必須有空格,空格後到換行符前的內容都是文件名。 文件不存在也不會報錯。若是一個腳本有多個命令寫到同一個文件中,那麼每一個命令的內容將追加到文件中。並且每一個腳本最多隻能打開十個文件。

使用-n能夠阻止模式空間的行被自動輸出,可是讀命令的結果仍然轉到標準輸出。

退出

退出命令[line-address]q, 會使sed中止讀取新的輸入行,並中止將他們送到標準輸出。它只適用於單行地址,一旦找到匹配行,腳本就結束。

 

awk

 echo a b c | awk 'BEGIN {one = 1;two=2} {print $(one+two)}'  #輸出c

 分隔符:

awk -F"\t" 或者 BEGIN{ FS=","} ,可使用正則。 輸出分隔,OFS="\t",OFS能夠從新定義爲一系列字符。

print $1,$2  逗號使個字段之間用空格隔開。不用逗號則各字段連在一塊兒,print $1 "," $2  ,輸出"$1逗號$2"。 輸出域的分隔符默認是一個空格,保存在OFS中。如$ awk -F: '{print $1,$5}' test,$1和$5間的逗號就是OFS的值。

awk中RS,ORS,FS,OFS區別與聯繫

變量

awk中可使用轉義序列。變量,運算符,表達式,控制結構和C類似。變量無需加$符號,未初始化的變量爲空或0。  每一個變量有字符型值和數值型值,不包含數字的字符串爲0.

空格是字符串鏈接操做符。Z="hello" "world"

賦值操做符:++,--,[+-*/%^]= ,**=  ,關係操做符:>,<,>=,<=,==,!=, ~, !~ 匹配/不匹配。邏輯操做&&,||,! ,!能夠用於字符串,判斷字符串是否非空。 見awk編程: 複合表達式,都和C相似。 匹配能夠用於字符串變量也可用於/regex/. name=root; $1 ~ name 或者 $1 ~ /root/  貌似用正則的地方也能夠用字符串。

in操做符能夠判斷某個下標是否在數組中。條件操做 expr ? action1 : action2

改變當前記錄的字段數NF的值會有反作用,增長NF的值會建立新的空字段,並從新創建$0,字段由OFS的值分隔。

變量名    變量內容
ARGC    命令行參數的數量。
ARGIND    命令行正在處理的當前文件的AGV的索引。
ARGV    命令行參數數組。
CONVFMT    轉換數字格式。
ENVIRON    從shell中傳遞來的包含當前環境變量的數組。
ERRNO    當使用close函數或者經過getline函數讀取的時候,發生的從新定向錯誤的描述信息就保存在這個變量中。
FIELDWIDTHS    在對記錄進行固定域寬的分割時,能夠替代FS的分隔符的列表。
FILENAME  當前的輸入文件名。
FNR    當前文件的記錄號。
FS    輸入分隔符,默認是空格。
IGNORECASE    在正則表達式和字符串操做中關閉大小寫敏感。
NF    當前文件域的數量。
NR    當前文件記錄數。
OFMT    數字輸出格式。
OFS    輸出域分隔符。
ORS    輸出記錄分隔符。
RLENGTH    經過match函數匹配的字符串的長度。
RS    輸入記錄分隔符。
RSTART    經過match函數匹配的字符串的偏移量。
SUBSEP    下標分隔符。
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1,$2}' test1
 111|222
 333|444
 555|666
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1 OFS $2}' test1
 111|222
 333|444
 555|666
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $0}' test1
 111 222
 333 444
 555 666
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{NF=NF;print $0}' test1
 111|222
 333|444
 555|666
爲何第二種方法中的OFS生效呢?我的以爲,awk覺查到列有所變化時,就會讓OFS生效,沒變化直接輸出了。 能夠設置$1=$1

能夠用NF來引用最後一個字段。 $NF,$(2+3)

多行記錄

FS="\n"; RS="" 記錄分隔符爲空字符串,表明空行。 

OFS="\n"; ORS="\n\n"; 

格式化打印 

printf(format,[args]) , 圓括號可選。 Shell經常使用技巧(五) awk編程 , Awk學習筆記 ,Shell編程-awk

format的格式:%-width.precision specifier , 數值的默認precision爲"%.6g" ,默認精度能夠經過設置系統變量OFMT來改變,如"%.2f"。

向腳本傳遞參數

awk引用外部變量

控制結構,和C相同,if [else if] else, for(;;),while(){}, do{}while(),break,continue

next致使讀入下一個輸入行,並返回到腳本底部,能夠避免當前輸入行執行其餘操做  。 exit是輸入主循環退出,轉到END規則。沒有END或者在END中用exit則終止腳本的執行。exit可使用一個表達式做爲參數,做爲awk的退出狀態返回。

數組

a[sub]=value,沒必要指明數組大小,awk的全部數組都是關聯數組,下標可使字符串和數字。

遍歷:for( var in arr )do something with arr[var] ,訪問順序隨機。 eg: arr[grade]++ ,即便grade最初不在數組arr中。

重要的是記住awk中的全部下標都是字符串型的,即便使用數字做爲下標,awk自動將它們轉爲字符串,當使用浮點數作下標時向字符串轉可能會有影響。

成員測試: item in array, 存在返回1,不然返回0。   awk應用小結(全部命令行均經調試) 

split()建立數組: n=split(str, array, sep), 返回元素個數,sep能夠是正則。

刪除數組元素: delete array[sub]

模擬多維數組: array[3,2], 成員測試時下標必須放置在圓括號中。 if((i,j) in array)。 多維數組的下標分別解釋爲單獨的字符串,用系統變量SUBSEP鏈接,默認爲「\034」。

多維數組循環: for(item in array) split(item,sub,SUBSEP). 必須用split()函數來訪問單獨的下標份量,split使用下標item建立數組sub。

系統變量的數組: 命令行參數ARGV,下標0到ARGC-1,不包括腳本名和選項,ARGV[0]是'awk'。  ENVIRON環境變量數組,其中下標是環境變量的名字。

 能夠向ARGV數組添加元素,可是注意要同時增長ARGC的值,awk使用ARGC的值來獲得ARGV中有多少元素能夠處理。若是ARGV的元素值是一個空串awk將跳過它。

函數

數學函數...

取整int(),print int(100/3)

rand()生成0到1之間的浮點隨機數。srand()爲隨機數發生器設置一個種子數或者起點數,srand([x]),不帶參數是使用當前時間。

字符串函數:字符串的起始位置爲1,

sub(regex,s,[t=$0]),替換第一個出現的,成功返回1不然返回0. gsub(regex,s,[t=$0])返回替換的個數。正則用//包圍。 直接改變指定字符竄,返回的不是替換後的字符串。 和sed同樣,替換字符串中的&將被正則匹配的字符串代替。\&表明"&",在字符串中必須輸入兩個\\。

index(s,t)返回t在s中的位置,沒有指定s返回0. length([s=$0])。

match(s,regex),正則用//包圍,返回regex出現的起始位置,若沒有,返回0。設置RSTART和RLENGTH的值。能夠用在while循環中,但在每次循環中要改變已匹配的[RSTART..RSTART+RLENGTH]部分,使下次循環是再也不匹配已匹配的部分。   注意sub的正則在前面,match的正則在後面。

split(s,arr,sep)返回元素個數,沒有sep則用FS。

sprintf(fmt,ecpr),  substr(s,p,[n]),子串p開始最大長度爲n。 tolower(s), toupper(s)。

lowerChars="abcdef..."; f=substr($1,1,1); if(i=index(lowerChars,f)) $1=substr(upperChars,i,1) substr($1,2) #首字母改大寫

awk 用法 Awk 命令學習總結 Linux Shell經常使用技巧(五) awk編程 awk使用手冊

自定義函數

function name(arg1,arg2,..){ statements }  return 語句返回。

函數參數都是局部變量。 函數體重定義的變量默認爲全局變量。 能夠將局部的臨時變量列在參數列表末尾。 在參數列表中參數按順序接受傳遞來的值。其餘的參數初始化爲空串。

高級主題

getline函數用於從輸入中讀取另外一行。也能處理來自文件和管道的輸入。next語句也是讀取下一行,可是next語句將控制傳遞到腳本的頂部。getline函數獲得下一行但不改變腳本的控制。返回值,1:讀取一行, 0:到達文件末尾, -1:遇到錯誤。 儘管被稱爲一個函數,可是它相似於一個語句,且不能寫成getline()。   while(getline > 0) cmd=amd $0

當讀取新行後,getline將它賦給$0,並將它分解成字段,同時設置NF,NR,FNR。所以新行變成當前行。若是須要,能夠用getline讀取一行並將它賦給一個變量從而避免改變$0。 getline var

從文件中讀取:while( (getline < "data") > 0 ) ,"data"是一個文件名字符串。加括號是爲了防止混亂。

標準輸入讀取: getline [var] < "-"

將輸入賦值給變量:getline var 不是var = getline, 對$0沒有影響。輸入行沒有被分解爲字段,對NF沒有影響。但它遞增了記錄計數器NR, FNR。

從管道讀取: "who an i" | getline .將命令的結果賦給$0,同時設置系統變量。$0被改變,$1,NF等變量確定都跟着改變,它也是根據FS來分隔字段,因此要注意改變FS的地方。 即便$0不改變,NR, FNR也會改變。

當包含多個輸入行時getline一次讀取一行, 要讀取全部行就必須建立一個循環來執行getline直到再也不有輸出爲止。while("who" | getline)...注意:其中who命令值執行一次,可是getline則調用屢次。

 close()函數: 關閉打開的文件或管道。

由於:1. 每次只能代開必定數量的管道。 一般用在getline返回0或-1是,如close("who"). 2. 關閉管道使得你能夠運行用一個命令兩次。 3.爲了獲得一個輸出管道來完成它的工做,使用close()多是必要的,{some processing of $0 | "sort > tmpfile"}  END{close("sort > tmpfile")}

system()函數執行命令。然而它沒有產生可供程序處理的輸出。它返回被執行命令的退出狀態。 if(system("mkdir dale") != 0) print "failed!"

 直接向文件或管道輸出:

print和printf能夠用輸出重定向操做">"和">>"將結果直接寫入到文件中。  print > data.out 將記錄寫入data.out

print | command 直接暑促到管道。該命令在第一次執行時打開一個管道,並將當前記錄做爲輸入傳送給命令,換句話說這裏的命令只執行一次,但每執行一次print將提供另外一個輸入行。

相關文章
相關標籤/搜索