2016-11-15 54 views
0

我當前的GAWK腳本需要使用短語文件,並創建一個正則表達式模式數組,然後用\ t字符分割每行並循環每行的前10列,然後檢查它是否至少包含一個短語從模式數組中,如果有,則跳過該行並不將其打印到文檔中。GAWK concat變量FOR FOR

問題:

由於短語文件是大它創建迭代負荷,使劇本很慢。

(700個圖案×10列(由製表符分隔))×1000行。

解決方案:

爲了提高速度我想Concat的第一列10,並檢查是否整個字符串中包含的至少一個圖案。我無法弄清楚如何連接FOR循環中的行。

工作例如:

gawk 'BEGIN{ 
FS=" *\t *"; 
IGNORECASE=1; 

while(getline a < "'$phpath'") PATS["^.*"a".*$"] 
} 

{ 
    ok=1; 
    for(i=1;i<=10;i++){ 
     for(p in PATS){ 
      if($i ~ p){ 
      ok=0 
      } 
     } 
    } 

} 
ok {print}' "$f" > "$newPath$filename" 

我嘗試:

gawk 'BEGIN{ 
    FS=" *\t *"; 
    IGNORECASE=1; 

    while(getline a < "'$phpath'") PATS["^.*"a".*$"] 
    } 

    { 
     phrase=""; 
     space=" "; 
     ok=1; 

     for(i=1;i<=10;i++){ 
      phrase = $space $phrase $i 
     } 

     for(p in PATS){ 
      if($phrase ~ p){ 
       ok=0 
      } 
     } 

    } ok {print}' "$f" > "$newPath$filename" 

回答

1

在awk中,您使用$對其操作,其中$x的意思是「給我列的,其數量值是變量x

要獲得第一個10 colu MNS成字符串:

for (i=1; i<=10; i++) { 
     # not this => phrase = $space $phrase $i 
     phrase = space phrase $i 
    } 

for (p in PATS) { 
     if (phrase ~ p) { # <= no $ 
      ok = 0 
      break   # no match, so break the loop early 
     } 
    } 

awk中使用變量,如C,不喜歡shell或Perl


你也可以試試這個:

gawk -v patternfile="$phpath" ' 
    BEGIN { 
     FS = " *\t *" 
     IGNORECASE = 1 
     while ((getline a < patternfile) > 0) 
      PATS["^.*"a".*$"] 
    } 
    { 
     line = $0 
     NF = 10   # this truncates the current record to 10 fields 
     ok = 1 
     for (p in PATS) 
      if ($0 ~ p) { 
       ok = 0 
       break 
      } 
     if (ok) 
      print line 
    } 
' "$f" > "$newPath$filename" 
+0

感謝您提供非常明確的解釋和建議的解決方案。你的代碼看起來更輕量。在建議的解決方案中循環模式時,我需要休息嗎? –

+0

哎呀,是的。更新。 –

+1

由於getline將返回'-1',所以如果遇到讀取模式文件時出錯,會進入無限循環。您需要'while((getline a 0)',請參閱http://awk.freeshell.org/AllAboutGetline。您可以通過從patternfile中創建一個'|'分隔的字符串而不是填充數組來進行比較而無需循環。 –

0

這不是你的問題的答案,但也許到你的問題。

我明白你的問題是關於表現。

據我所知你的主要問題之一是你正在使用RegEx。讓我解釋一下我的觀點。在AWK中,當你使用這樣的正則表達式時:/ MyRegExp /,你使用的是正則表達式的編譯版本,所以每次你需要檢查匹配時只檢查它,但正如你正在使用RegEx這樣:「MyRegExp」,這是每次你想檢查一個字符串是否匹配時編譯的。

你真的在檢查RegEx嗎?也許你不是,功能'索引'對你來說足夠好。

爲什麼不嘗試構建腳本並運行它?相反,檢查對加載模式第二個文件的每一行,你創建一個這樣的腳本:

/pattern1/{ 
    print 
    next 
} 
/pattern2/{ 
    print 
    next 
} 
/pattern3/{ 
    print 
    next 
} 
... 
... 

然後用第二個文件運行它。無論如何,我希望這會有所幫助。

0
while(getline a < "'$phpath'") PATS["^.*"a".*$"] 

的RE ^.*"a".*$相當於a。而不是迭代模式,你可以直接用|來表示OR條件。

如果你的輸入文件是

every 
good 
boy 
does 
fine 

您的RE變得every|good|boy|does|fine和你的代碼減少到

$0 ~ pattern { 
    for (i=1; i<=10; i++) { 
     if($i ~ pattern) { 
      print "$f" > "$newPath$filename" # what's $f? 
      break 
     } 
    } 
} 

也就是說,先掃描整條生產線。如果發現某些內容,請重複前10列。我敢打賭,這比無條件地迭代它們要快。

+0

我需要模式,因爲列不包含精確的短語。 例如: '測試我的短語測試,測試,測試,測試,測試,測試,測試' 捕獲'我的短語'我需要正則表達式。 –