回到: "Linux系列文章" "Shell系列文章" "Awk系列文章" awk布爾值 在awk中,沒有像其它語言一樣專門提供true、false這樣的關鍵字。 但它的布爾值邏輯非常簡單: 數值0表示布爾假 空字元串表示布爾假 其餘所有均為布爾真 字元串"0"也是真,因為它是字元串 awk中,正則 ...
回到:
awk布爾值
在awk中,沒有像其它語言一樣專門提供true、false這樣的關鍵字。
但它的布爾值邏輯非常簡單:
- 數值0表示布爾假
- 空字元串表示布爾假
- 其餘所有均為布爾真
- 字元串"0"也是真,因為它是字元串
- 字元串"0"也是真,因為它是字元串
- awk中,正則匹配也有返回值,匹配成功則返回1,匹配失敗則返回0
- awk中,所有的布爾運算也有返回值,布爾真返回值1,布爾假返回值為0
awk '
BEGIN{
if(1){print "haha"}
if("0"){print "hehe"}
if(a=3){print "hoho"} # if(3){print "hoho"}
if(a==3){print "aoao"}
if(/root/){print "heihei"} # $0 ~ /root/
}'
awk中比較操作
strnum類型
awk最基本的數據類型只有string和number(gawk 4.2.0版本之後支持正則表達式類型)。但是,對於用戶輸入數據(例如從文件中讀取的各個欄位值),它們理應屬於string類型,但有時候它們看上去可能像是數值(例如$2=37
),而有時候有需要這些值是數值類型。
awk的數據來源:
- awk內部產生的,包括變數的賦值、表達式或函數的返回值。
- 從其它來源獲取到的數據,都是外部數據,也是用戶輸入數據,這些數據理應全部都是string類型的數據。
所以POSIX定義了一個名為"numeric string"的"牆頭草"類型,gawk中則稱為strnum類型。當獲取到的用戶數據看上去是數字時,那麼它就是strnum類型。strnum類型在被使用時會被當作數值類型。
註意,strnum類型只針對於awk中除數值常量、字元串常量、表達式計算結果外的數據。例如從文件中讀取的欄位$1
、$2
、ARGV數組中的元素等等。
$ echo "30" | awk '{print typeof($0) " " typeof($1)}'
strnum strnum
$ echo "+30" | awk '{print typeof($1)}'
strnum
$ echo "30a" | awk '{print typeof($1)}'
string
$ echo "30 a" | awk '{print typeof($0) " " typeof($1)}'
string strnum
$ echo " +30 " | awk '{print typeof($0) " " typeof($1)}'
strnum strnum
大小比較操作
比較操作符:
< > <= >= != == 大小、等值比較
in 數組成員測試
比較規則:
|STRING NUMERIC STRNUM
-------|-----------------------
STRING |string string string
NUMERIC|string numeric numeric
STRNUM |string numeric numeric
簡單來說,string優先順序最高,只要string類型參與比較,就都按照string的比較方式,所以可能會進行隱式的類型轉換。
其它時候都採用num類型比較。
$ echo ' +3.14' | awk '{print typeof($0) " " typeof($1)}' #strnum strnum
$ echo ' +3.14' | awk '{print($0 == " +3.14")}' #1
$ echo ' +3.14' | awk '{print($0 == "+3.14")}' #0
$ echo ' +3.14' | awk '{print($0 == "3.14")}' #0
$ echo ' +3.14' | awk '{print($0 == 3.14)}' #1
$ echo ' +3.14' | awk '{print($1 == 3.14)}' #1
$ echo ' +3.14' | awk '{print($1 == " +3.14")}' #0
$ echo ' +3.14' | awk '{print($1 == "+3.14")}' #1
$ echo ' +3.14' | awk '{print($1 == "3.14")}' #0
$ echo 1e2 3|awk ’{print ($1<$2)?"true":"false"}’ #false
採用字元串比較時需註意,它是逐字元逐字元比較的。
"11" < "9" # true
"ab" < 99 # false
邏輯運算
&& 邏輯與
|| 邏輯或
! 邏輯取反
expr1 && expr2 # 如果expr1為假,則不用計算expr2
expr1 || expr2 # 如果expr1為真,則不用計算expr2
# 註:
# 1. && ||會短路運算
# 2. !優先順序高於&&和||
# 所以`! expr1 && expr2`等價於`(! expr1) && expr2`
!
可以將數據轉換成數值的1或0,取決於數據是布爾真還是布爾假。!!
可將數據轉換成等價布爾值的1或0。
$ awk 'BEGIN{print(!99)}' # 0
$ awk 'BEGIN{print(!"ab")}' # 0
$ awk 'BEGIN{print(!0)}' # 1
$ awk 'BEGIN{print(!ab)}' # 1,因為ab變數不存在
$ awk 'BEGIN{print(!!99)}' # 1
$ awk 'BEGIN{print(!!"ab")}' # 1
$ awk 'BEGIN{print(!!0)}' # 0
$ awk 'BEGIN{print(!!ab)}' # 0
由於awk中的變數未賦值時預設初始化為空字元串或數值0,也就是布爾假。那麼可以直接對一個未賦值的變數執行!
操作。
下麵是一個非常有意思的awk技巧,它通過多次!
對一個flag取反來實現只輸出指定範圍內的行。
# a.txt
$1==1{flag=!flag;print;next} # 在匹配ID=1的行時,flag=1
flag{print} # 將輸出ID=2,3,4,5的行
$1==5{flag=!flag;next} # ID=5時,flag=0
藉此,就可以讓awk實現一個多行處理模式。例如,將指定範圍內的數據保存到一個變數當中去。
$1==1{flag=!flag;next}
flag{multi_line=multi_line$0"\n"}
$1==5{flag=!flag;next}
END{printf multi_line}
運算符優先順序
優先順序從高到低:man awk
()
$ # $(2+2)
++ --
^ **
+ - ! # 一元運算符
* / %
+ -
space # 這是字元連接操作 `12 " " 23` `12 " " -23`
| |&
< > <= >= != == # 註意>即是大於號,也是print/printf的重定向符號
~ !~
in
&&
||
?:
= += -= *= /= %= ^=
對於相同優先順序的運算符,通常都是從左開始運算,但下麵2種例外,它們都從右向左運算:
- 賦值運算:如
= += -= *=
- 冪運算
a - b + c => (a - b) + c
a = b = c => a =(b = c)
2**2**3 => 2**(2**3)
再者,註意print和printf中出現的>
符號,這時候它表示的是重定向符號,不能再出現優先順序比它低的運算符,這時可以使用括弧改變優先順序。例如:
awk 'BEGIN{print "foo" > a < 3 ? 2 : 1)' # 語法錯誤
awk 'BEGIN{print "foo" > (a < 3 ? 2 : 1)}' # 正確