coolshell是個很不錯的小站,請大家多關注
awk
awk [options] 'script' files
下面我們較長的描述script區域
關鍵字
{} 代表對每一行進行處理的語句
BEGIN{} 代表對每一行進行處理前執行的語句
END{} 代表對每一行進行處理後執行的語句
$ cat score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
cat cal.awk
#!/bin/awk -f
#運作前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#運作中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#運作後
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}
awk -f cal.awk score.txt
語句
1.列印 '{print $1,$2 ...}'
列印檔案中每一行的第一列和第二列;其中$1代表第一列,$2代表第二列,以此類推,$0代表每一列,即一整行
2.格式化輸出 'printf "%-20s %-20s %s\n",$4,$5,$6 '
3.過濾 '$3==0 && $6=="LISTEN" '
awk支援比較運算符 == != > < >= <=; 字元串可以使用 “ ”
第二種過濾是 字元串比對 ~ / pattern / pattern比對時可以 使用 | ,取反 ' !/pattern/ '
'$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}'
當然也可以 在外面比對 awk '/LISTEN/ ' filename
4.拆分檔案 awk 'NR!=1{print > $6} '
NR!=1表示排除第一行,然後把第六列相同的值儲存到命名為該值的檔案中
複雜些加上條件語句
'NR!=1{
if($6 ~ /TIME|ESTABLISHED/) print > "1.txt";
else if($6 ~ /LISTEN/) print > "2.txt";
else print > "3.txt" }'
5.内置變量
$0 | 目前記錄(這個變量中存放着整個行的内容) |
$1~$n | 目前記錄的第n個字段,字段間由FS分隔 |
FS | 輸入字段分隔符 預設是空格或Tab |
NF | 目前記錄中的字段個數,就是有多少列 |
NR | 已經讀出的記錄數,就是行号,從1開始,如果有多個檔案話,這個值也是不斷累加中。 |
FNR | 目前記錄數,與NR不同的是,這個值會是各個檔案自己的行号 |
RS | 輸入的記錄分隔符, 預設為換行符 |
OFS | 輸出字段分隔符, 預設也是空格 |
ORS | 輸出的記錄分隔符,預設為換行符 |
FILENAME | 目前輸入檔案的名字 |
(1).FS & OFS 分隔符
awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd 使用:作為分隔符,而不是space
也可以awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd,其中想要制定多個分隔符 可以使用-F ' [;:] '
(2).NR & FNR 分隔符
如果使用過濾條件,有想要列印出第一行的所有内容,可以使用NR==1;FNR表示自己的行号
awk '$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}' netstat.txt
awk程式設計
1.變量指派
可以直接使用變量,預設初始化為0,妥當做法是顯示初始化
2.計算運算符 + - * / 甚至還支援 += ++ 等
3.條件語句,循環語句
if (expression) {
statement1;
} else if (expression1) {
statement2;
} else {
statement3;
}
awk中的循環語句同樣借鑒于C語言,支援while、do/while、for、break、continue,這些關鍵字的語義和C語言中的語義完全相同。
'NR!=1{a[$6]++;} END {for (i in a) print i ", " a[i];}'
檢視每個程序占用多少記憶體 ps aux | awk 'NR!=1{a[$1]+=$6;} END { for(i in a) print i ", " a[i]"KB";}'
8.length
awk 'length>80' file
9.使用環境變量
options使用-v 在script中使用 ENVIRON["value name"] 代表環境變量标簽
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sed
最近懶了,來來來,把sed補上
玩sed需要熟練操作正規表達式
sed的很多操作方式非常類似于vim
sed [options] "commands" filename
老規矩,先看commands
指令
替換
和vim一樣
sed “s/source/dest/g" filename
如果想要使用單引号,最好外包雙引号,而且使用雙引号可以哦那個過\ 轉意其他字元‘
1)簡單正規表達式
^開頭 ^s 比對以s開頭
$結尾 s$比對以s結尾
\< 詞頭 \<s 以s開頭的詞
\> 詞尾 \>s 以s結尾的詞
. 表示任何單個字元
* 表示某個字元出現了0次或多次 ? 表示某個字元出現了1次或多次
[] 字元集合 [abc] 表示比對 a 或者 b 或者 c ;如果 [^a] 表示a取反,除了a之外的字元
可以是用正規表達式來做字元替換,下面介紹寫例子
2) 替換的文本寫回到源檔案
兩種辦法 1.使用管道 sed “commands" filename > filename
2.使用options -i sed "commands" filename 即可
3)在每行開頭加入 #
sed "s/^/#/g" filename
4) 去掉html的tags
sed 's/ < [^>] * > / / g " filename
5)替換特定行和特定列
sed "3,$ s/source/dest/g" filename 替換第三行到最後一行所有
sed "3,$ s/source/dest/1" filename 隻替換第二個符合source的字段
sed "1,3 s/source/dest/3g" filename 替換第一行到第三行的每一行中第三個到最後一個符合source的字段
6)多個比對
兩種辦法。1.在commands中使用分号; sed " s/source1/dest1/g ; s/source2/dest2/g " filename
2.使用options -e sed -e "s/source1/dest1/g" -e "s/source2/dest2/g" filename
7)&符号
可以使用&值代前面的pattern
sed "s/pattern/[&]/g" filename 這樣就在所有patter左右加了[]
8)圓括号比對
比對出來的pattern的第一個用 \1 指代,以此類推
sed “s/ pattern1, pattern2 / \1:\2/g " filename
其他指令
分為n指令,c,p,a&i,d指令等
1)N指令,把下一行的内容納入緩沖區當作比對
sed 'N;s/\n/,/' pets.txt 将兩行合并為一行,并且中間使用,分割
2)插入 a & i
sed "$ a test " filename 後面插入
sed "$ i test " filename 前面插入
也可以使用比對
sed "/my/a ----" my.txt
3)替換c指令
sed "2 c test" my.txt
sed "/fish/ c test" my.txt
4) 删除d指令
同理,,,
5)列印p指令
高階sed待續,哈哈
http://sebug.net/paper/books/awk/
http://coolshell.cn/articles/9070.html
http://coolshell.cn/articles/9104.html