awk
awk的工作模式是掃描文件中的每一行, 并且對符合條件的行進行處理, 處理的時候可以針對整行, 也可以針對行里的每個域。
所以awk兩個最重要的參數就是:模式和動作, 根據模式找出符合條件的行, 然后執行指定的動作。
不指定模式的話默認就對于每一行都執行動作, 不指定動作的話默認就是把符合條件的行打印在屏幕上。
awk的語法
awk的語法如下
awk [options] 'pattern {action}' filename
或者
awk [options] -f script filename
第二種形式就是把'pattern {action}'
寫在了文件里。
options
是可選的, 最常用的有兩個:
-
-F seperator
,用來指定域的分隔符, 默認的分隔符是空格, 也就是每一個單詞是一個域。可以指定多個域分隔符,此時應該把多個與分隔符放置在方括號中, 比如awk -F '[:-]' '{print $1,$3}' filename
, 使用:
或者-
作為域分隔符, 并且打印出第一個和第三個域 -
-v var=value
,用來指定一個用戶自定義的變量, 可以稍后再pattern或者action中使用。
awk可以跟上多個pattern和action, 所以更一般的形式如下:
awk [options] 'pattern1 {action1} pattern2 {action2}...patternN {action}' filename
其中awk有內置的兩個action, 叫做BEGIN
和END
,BEGIN在awk開始遍歷file的時候執行,一般可以用來打印開始log或者定義在解析中用到的變量。 END在awk遍歷文件結束的時候執行,一般用來打印結束的log.
所以awk的更一般的形勢是:
awk [options] 'BEGIN {action} patternN {actionN} END {action}' filename
務必要記住, 在awk的單引號中, 所有的action都是在花括號中, 在花括號外面的都是pattern,BEGIN和END可以看做是兩個特殊的pattern
花括號內可以有多個操作, 每個操作之間使用分號;分割, awk的操作支持使用所有的shell命令
awk的模式
awk的模式可以通過以下方式指定:
- 正則表達式,正則表達式一般都放在
/regular/
中間 - 關系表達式, 比如字符串或者數值大小的比較什么的
-
域 ~ 正則表達式
,域 !~ 正則表達式
, 域或者變量符合或者不符合某個正則表達式,~
和!~
分別表示域或者變量符合某個正則表達式或者不符合某個正則表達式 - 使用正則表達式指定的范圍, 比如
/pattern1/,/pattern2/
awk內置的環境變量, 只介紹最常用的
- $n 第n個域,默認是以空格分割的
- $0 當前完整的記錄,awk把每一個處理過的行都稱為一個記錄
- FILENAME 當前正在處理的文件的名稱
- NR number of record, 當前已經處理過的記錄的個數
- NF number of field, 當前正在處理的記錄包含的域的個數
- FS field seperator域分隔符, 默認為空格
- RS record seperator記錄分隔符, 默認為換行符
awk支持的運算符
awk支持編程語言中幾乎所有的運算符,+ - * / ++ -- > < <= >= != && || ! += -= *= /= ?:
包括但不局限于加減乘除, 自加自減, 邏輯與或非, 三目運算符等。
還有兩個非常值得注意的運算符:
-
~ !~
匹配正則表達式和不匹配正則表達式 -
in
某個變量或者域是否屬于數組的成員
下面來看一個匹配和不匹配正則表達式操作符的例子
awk '$1 ~/^root/' filename
,打印出來第一個域以root開頭的所有記錄
下面看一些例子
-
awk '$1 + $3 >100' filename
打印所有第一個域和第三個域的和大于100的記錄 -
awk '/root/,/chico/' filename
打印第一個包含root的行和第一個包含chico的行中間的所有行 -
awk '/^(no|so)/' filename
打印所有以no或者so開頭的行 -
awk '/^(no|so)/ {print $2}' filename
打印所有以no或者so開頭的行的第二個域 -
awk '$1 ~ /[0-9][0-9]$/ {print $1}'filename
打印以兩個數字結尾的行的第一個域 -
awk '$1 >10 && $2 <30 {print $0}' filename
打印第一個域大于10并且第二個域小于30的所有行 -
awk '/^chicodong/{print $2}' filename
打印以chicodong開頭的行的第二個域
在看一點復雜的, 在awk中使用變量。
比如awk '$1 ~ /^test/ {count=$2+$3;print count}' filename
,count就是一個變量,這個count=$1+$2
是賦值操作, 必須要放在action中。上面這個例子的含義是找出所有以test開頭的行, 并且打印出來第二個域和第三個域的和。
更改域的值
看下面一個例子
awk '{$2=$1+10; print $2}' filename
, 就是把第二個域的值更改為第一個域的值加10.
再看一個例子
awk '$1=="root"{$1="chico";print}' filename
,如果第一個域是root,那么就把第一個域改成chico,并且打印出來。
awk內置的函數, 最常用的是printf, 用來格式化輸出特別方便
echo "65"|awk '{print "%c\n", $0}'
, 可以打印出65對應的ASCII字符串。