亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 24670062 | 回復(fù): 24670062
打印 上一主題 下一主題

[學(xué)習(xí)共享] 文本編輯的一點(diǎn)心得--awk篇 [復(fù)制鏈接]

論壇徽章:
23
15-16賽季CBA聯(lián)賽之吉林
日期:2017-12-21 16:39:27白羊座
日期:2014-10-27 11:14:37申猴
日期:2014-10-23 08:36:23金牛座
日期:2014-09-30 08:26:49午馬
日期:2014-09-29 09:40:16射手座
日期:2014-11-25 08:56:112015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:0315-16賽季CBA聯(lián)賽之山東
日期:2017-12-21 16:39:1915-16賽季CBA聯(lián)賽之廣東
日期:2016-01-19 13:33:372015亞冠之山東魯能
日期:2015-10-13 09:39:062015亞冠之西悉尼流浪者
日期:2015-09-21 08:27:57
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-09-23 13:24 |只看該作者 |倒序?yàn)g覽
本帖最后由 ly5066113 于 2014-04-30 08:35 編輯

本文模仿十三問,以提問和回答的方式介紹awk的一些基礎(chǔ)知識。論壇里awk高手眾多,有錯誤的地方還請大家指正。


本文所有用例的測試環(huán)境采用unix-center的ubuntu服務(wù)器
http://www.unix-center.net/

具體版本如下:
  1. ly5066113@ubuntu:~$ uname -a
  2. Linux ubuntu 2.6.24-22-generic #1 SMP Mon Nov 24 19:35:06 UTC 2008 x86_64 GNU/Linux
  3. ly5066113@ubuntu:~$ bash --version
  4. GNU bash, version 3.2.39(1)-release (x86_64-pc-linux-gnu)
  5. Copyright (C) 2007 Free Software Foundation, Inc.
  6. ly5066113@ubuntu:~$ awk --version
  7. GNU Awk 3.1.6
  8. Copyright (C) 1989, 1991-2007 Free Software Foundation.
復(fù)制代碼
一、RS 與 ORS 差在哪

我們經(jīng)常會說,awk是基于行列操作文本的,但如何定義“行”呢?這就是RS的作用。
默認(rèn)情況下,RS的值是\n。下面通過實(shí)例來理解下RS。
  1. ly5066113@ubuntu:~$ echo '1a2a3a4a5' | awk '{print $1}'
  2. 1a2a3a4a5
  3. ly5066113@ubuntu:~$ echo '1a2a3a4a5' | awk 'BEGIN{RS="a"}{print $1}'
  4. 1
  5. 2
  6. 3
  7. 4
  8. 5
復(fù)制代碼
我們可以看到,在更改了RS的值后,awk定義的行已經(jīng)不是我們實(shí)際意義中的行了。
上面RS固定的字符串,RS也可以定義為正則表達(dá)式。
  1. ly5066113@ubuntu:~$ echo '1ab2bc3cd4de5' | awk 'BEGIN{RS="[a-z]+"}{print $1,RS,RT}'
  2. 1 [a-z]+ ab
  3. 2 [a-z]+ bc
  4. 3 [a-z]+ cd
  5. 4 [a-z]+ de
  6. 5 [a-z]+
復(fù)制代碼
當(dāng)我們將RS設(shè)置為正則表達(dá)式的時候,RT這個變量就有作用了,RS的值始終為我們設(shè)定的正則,RT的值則是這個正則實(shí)際匹配到的內(nèi)容。
下面我們看看將RS設(shè)置為空會是什么情況
  1. ly5066113@ubuntu:~$ cat urfile
  2. 1

  3. 2


  4. 3








  5. 4
  6. ly5066113@ubuntu:~$ awk 'BEGIN{RS=""}{print $0}' urfile
  7. 1
  8. 2
  9. 3
  10. 4
復(fù)制代碼
如果RS被設(shè)置為空,那么awk會將連續(xù)的空行作為行分隔符,與RS設(shè)置成"\n\n+"有什么區(qū)別???
1、忽略文件開頭和結(jié)尾的空行。且文件不以記錄分隔符結(jié)束,即最后不是空行,會將最后一個記錄的尾\n去掉
2、設(shè)置RT變量未空
3、影響FS變量
這個怎么理解?對于1、2兩點(diǎn),當(dāng)作習(xí)題留給大家自己測試,3我們下節(jié)來講。

總結(jié)下RS的3種情況:
1) 非空字符串
   以固定字符串作為行分隔符,同時設(shè)置變量RT為固定字符串
2) 正則表達(dá)式
   以正則表達(dá)式作為行分隔符,同時設(shè)置變量RT為正則表達(dá)式實(shí)際匹配到的字符串
3) 空字符
   以連續(xù)的空行作為行分隔符,如果FS為單個字符,會將\n強(qiáng)制加入到FS變量中

理解了RS,再來理解ORS就簡單了。RS是awk讀取文件時的行分隔符,ORS則是awk輸出時的行結(jié)束符。
更簡單的講,就是awk在輸出時,會在每行記錄后面增加一個ORS變量所設(shè)定的值。
ORS的值只能設(shè)定為字符串,默認(rèn)情況下,ORS的值是\n
  1. ly5066113@ubuntu:~$ seq 5 | awk '{print $0}'
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. ly5066113@ubuntu:~$ seq 5 | awk 'BEGIN{ORS="a"}{print $0}'
  8. 1a2a3a4a5a
復(fù)制代碼
我們平常用的 print $0 等價于 printf $0 ORS


二、FS 與 OFS 差在哪

RS是awk用來定義“行”的,那么FS就是awk用來定義“列”的。
設(shè)置變量 FS 與使用 -F 參數(shù)是一樣的。
  1. ly5066113@ubuntu:~$ echo '1,2' | awk -F , '{print $1}'
  2. 1
  3. ly5066113@ubuntu:~$ echo '1,2' | awk 'BEGIN{FS=","}{print $1}'
  4. 1
復(fù)制代碼
與 RS 類似,F(xiàn)S 同樣可以設(shè)置為正則表達(dá)式
  1. ly5066113@ubuntu:~$ echo '1ab2bc3cd4de5' | awk 'BEGIN{FS="[a-z]+"}{print $1,$2,$5}'
  2. 1 2 5
復(fù)制代碼
FS 有1個特例,就是將FS設(shè)置為一個空格,F(xiàn)S=" " ,這也是FS的默認(rèn)值
  1. In the special case that FS is a single space, fields are separated by runs of spaces and/or tabs and/or newlines.
復(fù)制代碼
此時,awk會將連續(xù)的 空格 或 制表符(\t) 或 換行符(\n) 作為列的分隔符
那么,F(xiàn)S=" " 與 FS="[ \t\n]+" 有區(qū)別么???
答案是肯定的
  1. ly5066113@ubuntu:~$ echo ' 1 2' | awk 'BEGIN{FS=" "}{print $1}'
  2. 1
  3. ly5066113@ubuntu:~$ echo ' 1 2' | awk 'BEGIN{FS="[ \t\n]+"}{print $1}'

復(fù)制代碼
當(dāng)FS=" "時,awk會自動去掉行首和行尾的 空格 或 制表符(\t) 或 換行符(\n),但FS="[ \t\n]+"是不會的
同樣,F(xiàn)S也可以設(shè)置為空
  1. ly5066113@ubuntu:~$ echo '123' | awk 'BEGIN{FS=""}{print $1,$2}'
  2. 1 2
復(fù)制代碼
當(dāng)FS被設(shè)置為空字符串的時候,awk會將一行記錄的每個字符做為單獨(dú)的一列
類似的,當(dāng)我們想以固定的長度來分隔列的時候,可以使用 FIELDWIDTHS 來代替 FS
例如,一行記錄的前3個字符作為第一列,接下來的2個字符作為第二列,接下來的4個字符作為第三列
  1. ly5066113@ubuntu:~$ echo '123456789' | awk 'BEGIN{FIELDWIDTHS="3 2 4"}{print $1,$2,$3}'
  2. 123 45 6789
  3. ly5066113@ubuntu:~$ echo '123456789' | awk 'BEGIN{FIELDWIDTHS="3 2 3"}{print $1,$2,$3}'
  4. 123 45 678
  5. ly5066113@ubuntu:~$ echo '123456789' | awk 'BEGIN{FIELDWIDTHS="3 2 5"}{print $1,$2,$3}'
  6. 123 45 6789
復(fù)制代碼
如果定義的長度小于實(shí)際的長度,awk會截斷,如果大于實(shí)際長度,則以實(shí)際長度為準(zhǔn)。

總結(jié)下FS的4種情況:
1) 非空字符串
   以固定字符串作為列分隔符
2) 正則表達(dá)式
   以正則表達(dá)式作為列分隔符
3) 單個空格
   以連續(xù)的 空格 或 制表符(\t) 或 換行符(\n)作為列分隔符
4) 空字符
   以每個字符做為單獨(dú)的一列

接下來我們來看看上節(jié)提到的問題:
當(dāng) RS="" 時,會將\n強(qiáng)制加入到FS變量中
  1. ly5066113@ubuntu:~$ cat urfile
  2. 1
  3. a

  4. 2
  5. a


  6. 3
  7. ly5066113@ubuntu:~$ awk -v RS="" '{print "#" $0 "#"}' urfile
  8. #1
  9. a#
  10. #2
  11. a#
  12. #3#
  13. ly5066113@ubuntu:~$ awk -F "b" -v RS="" '{print $1}' urfile
  14. 1
  15. 2
  16. 3
  17. ly5066113@ubuntu:~$ awk -F "c" -v RS="" '{print $1}' urfile
  18. 1
  19. 2
  20. 3
  21. ly5066113@ubuntu:~$ awk -F "c" -v RS="\n\n+" '{print "#" $1 "#"}' urfile
  22. #1
  23. a#
  24. #2
  25. a#
  26. #3
  27. #
復(fù)制代碼
如果FS為單個字符,\n始終存在在 FS 中,而 RS="\n\n+" 則不會。

了解的 FS ,我們來看看 OFS ,F(xiàn)S是awk讀入記錄時的列分隔符,OFS則是awk輸出時的列分隔符。
我們平時使用的 print $1,$2 等價于 print $1 OFS $2
  1. ly5066113@ubuntu:~$ echo '1 2' | awk -v OFS="|" '{print $1,$2}'
  2. 1|2
  3. ly5066113@ubuntu:~$ echo '1 2' | awk -v OFS="|" '{print $1 OFS $2}'
  4. 1|2
復(fù)制代碼
如果一行記錄有很多列,同時想改變輸出的分隔符,print $1,$2,$3 ... 豈不是很麻煩?
當(dāng)然有簡單的方法:
  1. ly5066113@ubuntu:~$ echo '1 2 3 4 5' | awk -v OFS="|" '{print $0}'
  2. 1 2 3 4 5
  3. ly5066113@ubuntu:~$ echo '1 2 3 4 5' | awk -v OFS="|" '{$1=$1;print $0}'
  4. 1|2|3|4|5
  5. ly5066113@ubuntu:~$ echo '1 2 3 4 5' | awk -v OFS="|" '{NF+=0;print $0}'
  6. 1|2|3|4|5
復(fù)制代碼
為了使OFS的設(shè)置生效,需要改變 $0 ,這里我們是對 awk 撒了個小謊
$1=$1 或者 NF+=0, $0 本身的內(nèi)容實(shí)際上沒有任何改變,只是為了使 OFS 的設(shè)置生效

在理解了 RS 和 FS 之后,我們來回顧開始的那句話:“awk是基于行列操作文本的”
這個說法實(shí)際上不是很準(zhǔn)確,因?yàn)樵诟淖兞?RS 后,awk 中的“行”已經(jīng)不是一般的“行”了
同樣,改變了 FS 后,awk 中的“列”也已經(jīng)不是一般的“列”了
因此,準(zhǔn)確的應(yīng)該這樣講:“awk是基于 記錄(record) 和 域(field) 操作文本的”


三、0 與 "0" 差在哪

我們先來看一個例子:
  1. ly5066113@ubuntu:~$ awk 'BEGIN{if(0) print "true";else print "false"}'
  2. false
  3. ly5066113@ubuntu:~$ awk 'BEGIN{if("0") print "true";else print "false"}'
  4. true
復(fù)制代碼
為什么同樣是 0 ,結(jié)果卻不一樣?
其實(shí)要解釋這個問題,只需要弄清楚awk中的“真”與“假”。
以下3種情況是“假”,其他情況都為“真”
1) 數(shù)字 0
2) 空字符串
3) 未定義的值
  1. ly5066113@ubuntu:~$ awk 'BEGIN{a=0;if(a) print "true";else print "false"}'
  2. false
  3. ly5066113@ubuntu:~$ awk 'BEGIN{a="";if(a) print "true";else print "false"}'
  4. false
  5. ly5066113@ubuntu:~$ awk 'BEGIN{if(a) print "true";else print "false"}'
  6. false
復(fù)制代碼
以上是普通的字符測試,對于是表達(dá)式的情況,先計算表達(dá)式,然后將結(jié)果按上面的情況測試
  1. ly5066113@ubuntu:~$ awk 'BEGIN{if(a=1) print "true";else print "false"}'
  2. true
  3. ly5066113@ubuntu:~$ awk 'BEGIN{if(a=0) print "true";else print "false"}'
  4. false
  5. ly5066113@ubuntu:~$ awk 'BEGIN{if(a="0") print "true";else print "false"}'
  6. true
  7. ly5066113@ubuntu:~$ awk 'BEGIN{if(a="") print "true";else print "false"}'
  8. false
  9. ly5066113@ubuntu:~$ awk 'BEGIN{if(a=a) print "true";else print "false"}'
  10. false
復(fù)制代碼
來看一個被大家稱為月經(jīng)的問題,awk如何去重?
  1. awk '! a[$0] ++'
復(fù)制代碼
在解釋之前,我們先要了解awk的一個特性:
awk 會根據(jù)語境來給未定義的變量賦初始值
  1. ly5066113@ubuntu:~$ awk 'BEGIN{print a "" 1}'
  2. 1
  3. ly5066113@ubuntu:~$ awk 'BEGIN{print a + 1}'
  4. 1
復(fù)制代碼
對于未定義的變量,如果要進(jìn)行字符串操作,會被賦成空字符串 ""
如果要進(jìn)行數(shù)學(xué)運(yùn)算,會被賦成數(shù)字 0

現(xiàn)在我們看看上面的代碼 ! a[$0] ++ 等價于 if(! a[$0] ++) print $0
對于首次出現(xiàn)的記錄,a[$0]的值是未定義的,由于后面的 ++ 是數(shù)學(xué)計算,所以a[$0]會被賦值成數(shù)字0
也是由于 ++ 操作符,會先取值,再計算,所以對于第一行記錄實(shí)際上是if(! 0) print $0
! 是取反,0 是假,! 0 就是真,那么就會執(zhí)行后面的 print $0
對于后面出現(xiàn)的重復(fù)記錄,a[$0] 經(jīng)過 ++ 的計算已經(jīng)變?yōu)?1、2、3 。。。
而 ! 1  ! 2  ! 3 ... 都為假,不會打印。

下面我們用黑哥的一段代碼來深刻體會一下,用awk打印奇數(shù)行:
  1. ly5066113@ubuntu:~$ seq 10 | awk 'i=!i'
  2. 1
  3. 3
  4. 5
  5. 7
  6. 9
復(fù)制代碼
你想明白了么?


四、NR 與 FNR 差在哪

NR與FNR在awk處理單個文件時是沒有區(qū)別的,處理多個文件時才有區(qū)別,我們先看個例子:
  1. ly5066113@ubuntu:~$ awk '{print FILENAME,"NR="NR,"FNR="FNR,$0}' a.txt b.txt c.txt
  2. a.txt NR=1 FNR=1 a
  3. a.txt NR=2 FNR=2 b
  4. a.txt NR=3 FNR=3 c
  5. b.txt NR=4 FNR=1 d
  6. b.txt NR=5 FNR=2 e
  7. b.txt NR=6 FNR=3 f
  8. c.txt NR=7 FNR=1 g
  9. c.txt NR=8 FNR=2 h
  10. c.txt NR=9 FNR=3 i
復(fù)制代碼
我們可以看到,NR是awk處理的總記錄數(shù),無論多少個文件,是一直累加的
而FNR是awk處理當(dāng)前文件的記錄數(shù),當(dāng)文件變化的時候是重新記數(shù)的

上面還有出現(xiàn)了一個變量FILENAME,這個變量的值就是awk當(dāng)前處理的文件的文件名
這里我們還有幾個變量需要了解:ARGV、ARGC、ARGIND
ARGV 是一個數(shù)組,它記錄著命令行的所有參數(shù)的值
ARGC 是命令行參數(shù)的個數(shù),(不包括-F、-v之類的awk參數(shù))
ARGIND 是ARGV數(shù)組的索引值,從0到ARGC-1
當(dāng)我們想去了解這些變量時,最簡單并且最有效的方法就是print
  1. ly5066113@ubuntu:~$ awk 'BEGIN{for(i=0;i<ARGC;i++) print "ARGV["i"]="ARGV[i]}{print ARGV[ARGIND],ARGIND,ARGC,$0}' [abc].txt
  2. ARGV[0]=awk
  3. ARGV[1]=a.txt
  4. ARGV[2]=b.txt
  5. ARGV[3]=c.txt
  6. a.txt 1 4 a
  7. a.txt 1 4 b
  8. a.txt 1 4 c
  9. b.txt 2 4 d
  10. b.txt 2 4 e
  11. b.txt 2 4 f
  12. c.txt 3 4 g
  13. c.txt 3 4 h
  14. c.txt 3 4 i
復(fù)制代碼
那么,ARGV[ARGIND]與FILENAME是否等價呢?
一般情況下,在awk處理文件時,兩者是一樣的
我們看看其他一些特殊的情況;
  1. ly5066113@ubuntu:~$ awk 'BEGIN{print FILENAME,ARGV[ARGIND]}'
  2. awk
  3. ly5066113@ubuntu:~$ awk 'BEGIN{getline;print FILENAME,ARGV[ARGIND],$0}'
  4. 123
  5. - awk 123
  6. ly5066113@ubuntu:~$ awk 'BEGIN{getline;print FILENAME,ARGV[ARGIND],$0}' a.txt
  7. a.txt a.txt a
  8. ly5066113@ubuntu:~$ awk 'BEGIN{getline<"a.txt";print FILENAME,ARGV[ARGIND],$0}'
  9. awk a
復(fù)制代碼
我們可以看到,在任何情況下,ARGV[ARGIND]始終是有值的,而FILENAME則不一定
  1. FILENAME    The name of the current input file.  If no files are specified on the command line, the value of FILENAME is "-".  However, FILENAME is undefined  inside
  2.                    the BEGIN block (unless set by getline).
復(fù)制代碼
下面我們用一個簡單的例子來理解下上面的內(nèi)容;
實(shí)現(xiàn) head 命令的功能
我想這個問題大家一定都會:
  1. awk 'NR<=10'
復(fù)制代碼
但這里我們希望是用awk處理多個文件,先來看看head處理多個文件的情況:
  1. ly5066113@ubuntu:~$ head [abc].txt
  2. ==> a.txt <==
  3. a
  4. b
  5. c

  6. ==> b.txt <==
  7. d
  8. e
  9. f

  10. ==> c.txt <==
  11. g
  12. h
  13. i
復(fù)制代碼
下面我們用awk來達(dá)到這個效果:
  1. ly5066113@ubuntu:~$ awk 'FNR==1{if(NR>1) print "";print "==> "FILENAME" <=="}FNR<=10' [abc].txt
  2. ==> a.txt <==
  3. a
  4. b
  5. c

  6. ==> b.txt <==
  7. d
  8. e
  9. f

  10. ==> c.txt <==
  11. g
  12. h
  13. i
復(fù)制代碼
讓我們再深入考慮下,head在處理文件時,無論文件多大,速度都是很快的,awk是否也可以呢?
上面的代碼當(dāng)然不可以,因?yàn)閍wk會處理整個文件,文件越大,速度越慢。
單個文件時可以這樣改寫:
  1. awk '1;NR==10{exit}'
復(fù)制代碼
多個文件時用exit就不行了,因?yàn)檫@樣awk處理一個文件后就結(jié)束了,我們可以用nextfile
  1. awk 'FNR==1{if(NR>1) print "";print "==> "FILENAME" <=="}1;FNR==10{nextfile}' [abc].txt
復(fù)制代碼
nextfile就是停止處理當(dāng)前文件,開始處理下一個文件。

我們再來看一個例子:
每三個文件合并為一個大文件
http://72891.cn/viewthread.php?tid=1792571
帖子里的方法是用while read的方式實(shí)現(xiàn)的,下面給一個純awk的方法:
  1. ly5066113@ubuntu:~$ awk 'FNR==1&&ARGIND%3==1{if(ARGIND>1){print s>f;s=""};f=sprintf("file%02d-%02d",ARGIND,ARGIND+2)}/^set/{print $0>f}/^plot/{$1=s?"":$1;s=s?s","$0:$0}END{print s>f}' file[0-9][0-9]
  2. ly5066113@ubuntu:~$ cat file01-03
  3. set arrow from 7,1633 to 8,1383
  4. set label "9575(100916104th)" at 6.5,1683
  5. set arrow from 7,1633 to 8,1383
  6. set label "9575(100916104th)" at 6.5,1683
  7. set arrow from 7,1633 to 8,1383
  8. set label "9575(100916104th)" at 6.5,1683
  9. plot "diff_029.file" with linespoints, "diff_029.file" with linespoints, "diff_029.file" with linespoints
  10. ly5066113@ubuntu:~$ cat file04-06
  11. set arrow from 7,1633 to 8,1385
  12. set label "9575(100916104th)" at 6.5,1685
  13. set arrow from 7,1633 to 8,1383
  14. set label "9575(100916104th)" at 6.5,1683
  15. set arrow from 7,1633 to 8,1383
  16. set label "9575(100916104th)" at 6.5,1683
  17. plot "diff_029.file" with linespoints, "diff_029.file" with linespoints, "diff_029.file" with linespoints
復(fù)制代碼
awk處理多個文件,是不是沒想象中那么復(fù)雜呢?


五、> 與 >> 差在哪

這里的>和>>是awk內(nèi)部的,不要和shell本身的>和>>混淆。
  1. ly5066113@ubuntu:~$ awk '{print NR,$0}' a.txt > b.txt
  2. ly5066113@ubuntu:~$ cat b.txt
  3. 1 a
  4. 2 b
  5. 3 c
  6. ly5066113@ubuntu:~$ awk '{print NR,$0 > "b.txt"}' a.txt
  7. ly5066113@ubuntu:~$ cat b.txt
  8. 1 a
  9. 2 b
  10. 3 c
復(fù)制代碼
第一句awk命令中的 > 就是shell本身的IO重定向,第二句awk命令中的 > 是awk內(nèi)部的IO重定向
awk中的 > 和 >> 類似perl的文件句柄,只在首次打開文件時有區(qū)別:
  1. ly5066113@ubuntu:~$ rm b.txt
  2. ly5066113@ubuntu:~$ awk '{print NR,$0 > "b.txt"}' a.txt
  3. ly5066113@ubuntu:~$ cat b.txt
  4. 1 a
  5. 2 b
  6. 3 c
  7. ly5066113@ubuntu:~$ rm b.txt
  8. ly5066113@ubuntu:~$ awk '{print NR,$0 >> "b.txt"}' a.txt
  9. ly5066113@ubuntu:~$ cat b.txt
  10. 1 a
  11. 2 b
  12. 3 c
  13. ly5066113@ubuntu:~$ awk '{print NR,$0 > "b.txt"}' a.txt
  14. ly5066113@ubuntu:~$ cat b.txt
  15. 1 a
  16. 2 b
  17. 3 c
  18. ly5066113@ubuntu:~$ awk '{print NR,$0 >> "b.txt"}' a.txt
  19. ly5066113@ubuntu:~$ cat b.txt
  20. 1 a
  21. 2 b
  22. 3 c
  23. 1 a
  24. 2 b
  25. 3 c
復(fù)制代碼
如果文件不存在,那么 > 和 >> 是一樣的
如果文件已經(jīng)存在,> 會覆蓋原文件,>> 則是追加

我們看到,在打開文件后,awk會一直向文件里追加記錄,那么可以在awk里關(guān)閉文件么?
這時我們就需要用到 close
  1. ly5066113@ubuntu:~$ awk '{print NR,$0 > "b.txt";close("b.txt")}' a.txt
  2. ly5066113@ubuntu:~$ cat b.txt
  3. 3 c
復(fù)制代碼
每次寫入后都關(guān)閉文件,那么下次寫入時就又重新打開文件
而每次打開又是覆蓋的方式,這樣b.txt里最后就只剩下a.txt的最后一行記錄

說到awk中的IO就不得不提 getline
  1. getline               Set $0 from next input record; set NF, NR, FNR.
  2. getline <file         Set $0 from next record of file; set NF.
  3. getline var           Set var from next input record; set NR, FNR.
  4. getline var <file     Set var from next record of file.
  5. command | getline [var]
  6.                       Run command piping the output either into $0 or var, as above.
復(fù)制代碼
getline的用法很靈活,可以從awk當(dāng)前處理的文件中獲取下一行記錄
也可以從外部的文件或者管道中獲取記錄,每次只取一行,賦給$0或者變量var
先來看個簡單的例子,實(shí)現(xiàn) grep -A1
  1. ly5066113@ubuntu:~$ seq 10 | grep -A1 5
  2. 5
  3. 6
  4. ly5066113@ubuntu:~$ seq 10 | awk '/5/{print;getline;print}'
  5. 5
  6. 6
復(fù)制代碼
再看個例子:
有沒有將兩個輸出或者說變量上每列分別合在一起的方法
http://bbs3.chinaunix.net/viewthread.php?tid=1752341
  1. $ var1='a
  2. > b
  3. > c
  4. > d'
  5. $ var2='A
  6. > B
  7. > C
  8. > D'
  9. $ export var2
  10. $ echo "$var1" | awk '{"echo \042$var2\042"|getline var2;print $1""var2}'
  11. aA
  12. bB
  13. cC
  14. dD
復(fù)制代碼
你看懂了么?


評分

參與人數(shù) 5可用積分 +26 收起 理由
blackold + 5 好。學(xué)習(xí)! 太窮了,最多只能5塊。
好看的附件 + 2 經(jīng)典原創(chuàng)
liaosnet + 4 原創(chuàng)·
bbgg1983 + 5 這個我喜歡
expert1 + 10 辛苦了,節(jié)日好!

查看全部評分

論壇徽章:
23
15-16賽季CBA聯(lián)賽之吉林
日期:2017-12-21 16:39:27白羊座
日期:2014-10-27 11:14:37申猴
日期:2014-10-23 08:36:23金牛座
日期:2014-09-30 08:26:49午馬
日期:2014-09-29 09:40:16射手座
日期:2014-11-25 08:56:112015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:0315-16賽季CBA聯(lián)賽之山東
日期:2017-12-21 16:39:1915-16賽季CBA聯(lián)賽之廣東
日期:2016-01-19 13:33:372015亞冠之山東魯能
日期:2015-10-13 09:39:062015亞冠之西悉尼流浪者
日期:2015-09-21 08:27:57
2 [報告]
發(fā)表于 2010-09-23 13:26 |只看該作者
今天先寫到這里,后續(xù)還會補(bǔ)充。

論壇徽章:
0
3 [報告]
發(fā)表于 2010-09-23 13:28 |只看該作者
果斷沙發(fā)
隨便瞎扯下最后那個
seq 10 | awk 'i=!i'
因?yàn)橐婚_始i=0
在第一行的時候 i=!i于是i=1 打印
第二行的時候 i=!i于是i=0不 打印
如此往復(fù)

論壇徽章:
23
15-16賽季CBA聯(lián)賽之吉林
日期:2017-12-21 16:39:27白羊座
日期:2014-10-27 11:14:37申猴
日期:2014-10-23 08:36:23金牛座
日期:2014-09-30 08:26:49午馬
日期:2014-09-29 09:40:16射手座
日期:2014-11-25 08:56:112015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:0315-16賽季CBA聯(lián)賽之山東
日期:2017-12-21 16:39:1915-16賽季CBA聯(lián)賽之廣東
日期:2016-01-19 13:33:372015亞冠之山東魯能
日期:2015-10-13 09:39:062015亞冠之西悉尼流浪者
日期:2015-09-21 08:27:57
4 [報告]
發(fā)表于 2010-09-23 13:32 |只看該作者
回復(fù) 3# lkk2003rty


呵呵,一開始 i=0 是如何得到的?

論壇徽章:
0
5 [報告]
發(fā)表于 2010-09-23 13:53 |只看該作者
本帖最后由 justlooks 于 2010-09-23 14:05 編輯

掃描第1行
i = ! i 第1個未定義 翻過來就是 i =1

打印偶數(shù)行
awk 'i++%2'

論壇徽章:
16
IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-08-24 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2015-10-14 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-10-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-11-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-15 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-21 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2016-08-16 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:17IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-08-14 06:20:00
6 [報告]
發(fā)表于 2010-09-23 14:04 |只看該作者
前排就坐圍觀,留名先,TIM哥辛苦了。節(jié)日快樂!

論壇徽章:
0
7 [報告]
發(fā)表于 2010-09-23 14:05 |只看該作者
牛逼之人  先標(biāo)記下  慢慢看 我被這個awk  折磨得傷心了

我不知道到底是不是該好好學(xué),因?yàn)槟壳皶r間緊,那么想先學(xué)perl

論壇徽章:
16
IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-08-24 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2015-10-14 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-10-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-11-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-15 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-21 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2016-08-16 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:17IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-08-14 06:20:00
8 [報告]
發(fā)表于 2010-09-23 14:12 |只看該作者
本帖最后由 expert1 于 2010-09-23 16:39 編輯

借寶地問個問題。
x    abcd
y    0,1
z    a,b,c

變成:
x abcd y 0 z a
x abcd y 0 z b
x abcd y 0 z c
x abcd y 1 z a
x abcd y 1 z b
x abcd y 1 z c
===================
規(guī)則:y (0/1) z (a/b/C)有6種情況

實(shí)際上就是第一行不變,然后2,3行的$2組合有3x2=6種。當(dāng)然文件內(nèi)容再加一行的話繼續(xù)3x2x? (?是下一行第一列的值的個數(shù)了。實(shí)際上就是一個組合了。)

我的思路是,NR==1記錄第一行,NR>1,a[$1]=$2,遍歷a然后split{a,c)}遍歷打印,但是輸出順序不符合。

當(dāng)然直接split,2個for足以搞掂這個問題。但是當(dāng)行數(shù)很多的時候,那要多少個for呀,所以有無好的辦法,按照我的那個思路或別的?

論壇徽章:
16
IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-08-24 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2015-10-14 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-10-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-11-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-15 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-21 06:20:00綜合交流區(qū)版塊每日發(fā)帖之星
日期:2016-08-16 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:17IT運(yùn)維版塊每日發(fā)帖之星
日期:2015-08-14 06:20:00
9 [報告]
發(fā)表于 2010-09-23 14:16 |只看該作者
回復(fù) 2# ly5066113


    TIM哥節(jié)日快樂,看下我樓上的那個問題,有無好的思路呀?謝謝了!

論壇徽章:
33
ChinaUnix元老
日期:2015-02-02 08:55:39CU十四周年紀(jì)念徽章
日期:2019-08-20 08:30:3720周年集字徽章-周	
日期:2020-10-28 14:13:3020周年集字徽章-20	
日期:2020-10-28 14:04:3019周年集字徽章-CU
日期:2019-09-08 23:26:2519周年集字徽章-19
日期:2019-08-27 13:31:262016科比退役紀(jì)念章
日期:2022-04-24 14:33:24
10 [報告]
發(fā)表于 2010-09-23 14:21 |只看該作者
學(xué)習(xí)
Tim哥辛苦了
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP