2013-10-22 115 views
4

AWK能夠解析領域的十六進制數字:十六進制文字

$ echo "0x14" | awk '{print $1+1}' 
21 <-- correct, since 0x14 == 20 

然而,它似乎並沒有與十六進制文字處理措施:

$ echo "0x14" | awk '$1+1<=21 {print $1+1}' | wc -l 
1 <-- correct 
$ echo "0x14" | awk '$1+1<=0x15 {print $1+1}' | wc -l 
0 <-- incorrect. awk is not properly handling the 0x15 here 

有沒有解決辦法?

+0

可能的重複:http://stackoverflow.com/questions/3683110/how-to-make-calculations-on-hexadecimal-numbers-with-awk –

+2

@RobertoNavarro完全不同的問題。我在詢問如何直接在awk命令中使用十六進制字面值(如第三個awk命令所示) – SheetJS

+0

我一直在嘗試不同的變體,如果你願意,可以嘲笑這個,但是以爲我會在我點擊之前發佈它去睡覺:bash $ hex = 20; echo $((16#$ hex + 1))| echo'0x''awk'{printf「%x \ n」,$ 1;}'' –

回答

5

你在這裏處理兩個相似但不同的問題,非十進制數據和非 - 您的awk計劃中的文字文字。

the POSIX-1.2004 awk specification詞法約定

8. The token NUMBER shall represent a numeric constant. Its form and numeric value [...] 
    with the following exceptions: 
    a. An integer constant cannot begin with 0x or include the hexadecimal digits 'a', [...] 

所以AWK(假設你使用nawkmawk)的行爲 「正確」。 gawk(自版本3.1開始)默認情況下支持非十進制(八進制和十六進制)文字編號,但使用--posix開關會將其關閉,如預期的那樣。

在這樣的情況下正常的解決方法是使用所定義的數字串行爲,其中一個數字串是有效地被解析爲C標準atof()strtod()功能,支持0x -prefixed號碼:

$ echo "0x14" | nawk '$1+1<=0x15 {print $1+1}' 
<no output> 
$ echo "0x14" | nawk '$1+1<=("0x15"+0) {print $1+1}' 
21 

這裏的問題是,這種說法並不正確,因爲POSIX-1.2004 also states

A string value shall be considered a numeric string if it comes from one of the following: 
    1. Field variables 
    ... 
and after all the following conversions have been applied, the resulting string would 
lexically be recognized as a NUMBER token as described by the lexical conventions in Grammar 

UPDATE:gawk旨在「2008 POSIX.1003。1「,但請注意,自2008版(請參閱IEEE Std 1003.1 2013 edition awk here)允許strtod()和實現相關的行爲不需要數字符合詞彙約定,這應該(隱含地)支持INFNAN中的文本Lexical約定同樣修改,以便允許在十六進制常量與0x前綴

這不會表現(上給出的數字詞彙約束)相當的希望在gawk

$ echo "0x14" | gawk '$1+1<=0x15 {print $1+1}' 
1 

(注意是「錯誤的」數字a nswer,這已被隱藏通過|wc -l) 除非你使用--non-decimal-data太:

$ echo "0x14" | gawk --non-decimal-data '$1+1<=0x15 {print $1+1}' 
21 

參見:

此接受了答案,這SE question有一個可移植性的解決方法。

爲具有兩種類型的用於非十進制數字支持的選項是:

如果你搜索「AWK DEC2HEX」你可以找到後者的許多情況下,可通過一個在這裏使用。如果你想要像gawk的strtonum()這樣的東西,你可以得到一個便攜式awk版本here

+0

非常翔實!原來'(「0x15」+0)'在這裏工作。它是否也在gawk中工作(不帶-n) – SheetJS

+1

沒有任何選項,否:對於轉換,它被視爲「0」,然後是非十進制垃圾,因此在數字上爲0.如果使用「--posix」,那麼它可以工作,有點奇怪。還有什麼奇怪的是'-n'也使它工作。這可能是gawk/awk/POSIX的沙漏角落之一。 (對於獎勵積分:gawk-3.0.4中有一個錯誤,它在將「0x15」轉換爲十進制時導致1.3125(即21/16)...) –

1

您是否陷入舊版awk版本?我不知道有什麼方法可以用它來做十六進制數字的數學(你將不得不等待更好的答案:-)。我可以選擇Gawk

-n, - 非十進制數據:識別輸入數據中的八進制和十六進制值。謹慎使用此選項!

所以,要麼

echo "0x14" | awk -n '$1+1<=21 {print $1+1}' 

echo "0x14" | awk -n '$1+1<=0x15 {print $1+1}' 

回報

21 
+1

我不使用gnu awk,不幸的是'-n'選項不是可用,但讓我困惑的是,我的版本清楚地分析了輸入數據中的十六進制文字(如第一個命令「echo」0x14「| awk'{print $ 1 + 1}')所示。 – SheetJS

+0

@Nirk:但是,該命令不適用於我的版本(** GNU Awk 4.1.0 **)。它返回'1'。我只知道'gawk'的解決方法。抱歉。 – Birei

+0

現在這真的很有趣。我希望GNU版本能夠做到「正確的事情」。儘管如此,我從中學到了一些東西,所以得到了讚揚:) – SheetJS

1

你使用任何AWK好像是壞了,或者非POSIX至少包括:

$ echo '0x14' | /usr/xpg4/bin/awk '{print $1+1}' 
1 
$ echo '0x14' | nawk '{print $1+1}' 
1 
$ echo '0x14' | gawk '{print $1+1}' 
1 
$ echo '0x14' | gawk --posix '{print $1+1}' 
1 

獲取GNU AWK和使用strtonum()無處不在,你可以有一個十六進制數字:在awk輸入

$ echo '0x14' | gawk '{print strtonum($1)+1}' 
21 
$ echo '0x14' | gawk 'strtonum($1)+1<=21{print strtonum($1)+1}'    
21 
$ echo '0x14' | gawk 'strtonum($1)+1<=strtonum(0x15){print strtonum($1)+1}' 
21 
+1

我不認爲你讀過這個問題。 '$ echo「0x14」| awk'{print $ 1 + 1}''工作得很好。問題出現在模式中使用十六進制文字(就像在第三種情況下 - 如果十六進制文字正常工作,然後'$ echo「0x14」| awk'$ 1 + 1 <= 0x15 {print $ 1 + 1}'| wc -l'會是1,而不是0) – SheetJS

+0

我沒有讀過這個問題,重點是'echo「0x14」| awk'{print $ 1 + 1}''不能與你的awk「工作」。它產生你期望/希望的輸出,但這不是正確的輸出。所有其他的awk,包括我測試過的兩個不同的POSIX awk,產生相同的輸出,並且在它們自己處理一個十六進制數字字符串(它是一個字符串,而不是數字)時是一致的。產生一個人認爲它應該產生的輸出並不意味着它能夠工作,特別是當它在某些情況下的行爲僅僅如你所期望的那樣。 –

+0

@SheetJS這是因爲最初的問題也有點令人困惑......(至少是IMO)我也不得不讀兩遍才能弄清楚OP實際上在做些什麼。我甚至在本地攻擊了這裏的行,以瞭解哪個輸出是預期的,哪些不是。根據我的定義,「Clarity」將會是別的東西;) – syntaxerror