FORW中的GAWK concat变量

时间:2016-11-15 19:33:58

标签: bash awk gnu gawk

我当前的GAWK脚本使用短语文件,并创建正则表达式模式数组,然后按\ t \ t字符拆分每一行并循环每行的前10列,然后检查它是否包含来自模式数组的至少一个短语,如果它确实如此,它会跳过该行并且不会将其打印到文档中。

问题:

因为短语文件很大,所以会产生大量的迭代并使脚本变得非常慢。

  

(700个图案x 10列(由制表符\ t分隔))x 1000行。

解决方案:

为了提高速度,我想连接前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"

3 个答案:

答案 0 :(得分:1)

在awk中,您使用$类似解除引用运算符,其中$x表示“为我提供其编号为变量x的列的值“

将前10列放入字符串中:

    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"

答案 1 :(得分:0)

这不是你问题的答案,但可能是你的问题。

我了解您的问题与性能有关。

据我所知,您遇到的一个主要问题是您使用的是RegEx。让我解释一下我的观点。在AWK中使用这样的正则表达式:/ MyRegExp /时,您使用的是RegEx的编译版本,因此每次需要检查匹配时,您只需检查它,但正如您使用RegEx一样:&#34; MyRegExp&#34;,每次要检查字符串是否匹配时,都会编译它。

你真的在检查RegEx吗?也许你不是和功能&#39;索引&#39;对你来说已经足够了。

为什么不尝试构建脚本并运行它?而是根据加载的模式检查第二个文件中的每一行,您可以创建如下脚本:

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

然后用第二个文件运行它。无论如何,我希望它会有所帮助。

答案 2 :(得分: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列。我敢打赌,比无条件地迭代它们要快。