2014-07-24 105 views
0

我有一個文本文件,我需要在一個字段中標識某個模式。我正在使用AWK,並嘗試使用match()函數。AWK正則表達式匹配

的要求是,我需要看看下面的模式在數字

??????1? 
??????3? 
??????5? 
??????7? 

字符串存在即我只在倒數第二個數字是1,3,5,或7感興趣。

我有一個解決方案,看起來像這樣;

b = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]1[0-9]") 
    c = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]3[0-9]") 
    d = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]5[0-9]") 
    e = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]7[0-9]") 

    if (b || c || d || e) 
    { 
      print "Found a match" $23 
    } 

我認爲雖然我應該能夠更簡潔地寫出這樣的正則表達式;

b = match($23, "[0-9]{6}1[0-9]") 

但這不起作用。

我錯過了什麼,或者是我的正則表達式技巧(哪些不是很好),真的很糟糕嗎?

感謝預期

+0

你對此感興趣嗎?我們可以看到一整行數據嗎?腳本的其餘部分是否以任何方式轉換線條? –

回答

3

正則表達式的分隔符爲/.../,不"..."。當您在RE上下文中使用引號時,您告訴awk存在一個RE存儲在字符串文本中,並且該字符串文字被解析兩次,一次讀取腳本時,然後再次執行時,這會使您的RE規範如此之多適應雙解析更復雜。

所以,千萬不要寫:

b = match($23, "[0-9]{6}1[0-9]") 

寫:

b = match($23, /[0-9]{6}1[0-9]/) 

代替。

雖然這不是你的問題。您最可能遇到的問題是您正在調用不支持RE間隔的awk版本,如{6}。如果您使用的GNU AWK的是舊版本,那麼你可以通過添加--re-interval標誌啓用該功能:

awk --re-interval '...b = match($23, /[0-9]{6}1[0-9]/)...' 

但無論它是或者您使用的是AWK那只是不支持RE_intervals,最好的事情要做的是獲得更新版本的gawk。如果你喜歡

awk --re-interval '$23 ~ /[0-9]{6}[1357][0-9]/{print "Found a match", $23}' 

變化[0-9][[:digit:]]對語言環境的獨立性:

最後,你的整個腳本可以降低到。

直到最近,gawk默認不支持RE間隔的原因是,舊的awk不支持它們,因此在舊awk中執行時有一個RE爲a{2}b的腳本會一直在尋找那些5 chars和gawk並不希望舊腳本在gawk而不是舊awk中執行時被安靜地破壞。爲了方便我們的向後兼容性,一些版本的gawk傢伙正確地決定默認啓用RE間隔。

+0

很棒的回答。謝謝 不幸的是我被困在了我有的awk版本中,服務器不是我的管理版本。 – Nerdio

+0

你確定服務器上只有1個awk版本嗎?例如,Solaris自帶3(/ usr/bin/awk,/ usr/bin/nawk和/ usr/xpg4/bin/awk)。你碰巧知道你正在運行哪個awk版本(嘗試'awk --version'和/或只是告訴我們操作系統)? –

+1

感謝您的意見,刪除了我的答案並向上投票 - 我不知道AWK的正則表達式風格,並提供了一些希望語法兼容的想法。 – zx81

0

這裏是一個awk解決方案:

awk -v FS="" '$7~/(1|3|5|7)/' file 

通過設置FS不了了之,每個字符變成了場。然後我們可以測試場#7。

正如湯姆張貼。

awk -v FS="" '$7~/[1357]/' file 
+3

這並沒有考慮到輸入包含很多字段的事實,只有其中一個字段需要匹配。無論如何,使用'/ [1357] /'會更有意義。 –