awk 保留如果行包含“示例”

awk keep if line contains " example "

好的,所以我希望保留包含几个关键字的行,

列表示例:

Name:email:username #registered
Name2:email2:username2
Name3:email3:username3 #registered #subscribed #phonever
Name4:email4:username4 #unconfirmed

我想做的是提取包含“#registered, #subscribed, #phonever

的行

我想要的输出示例,

Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever

使用 awk(在固定字符串列表上使用正则表达式交替运算符 |):

awk '/#registered|#subscribed|#phonever/' file

/.../ 下的部分称为 awk pattern,对于匹配的行,它执行后面的操作(如 { ... })。但由于默认操作是:{ print [=22=] }(打印完整输入record/line),因此无需在此处指定。

sed 类似,你可以说:

sed -nE '/#registered|#subscribed|#phonever/p' file

但现在我们必须指定 -n 以默认跳过打印,并使用 p 命令仅打印与模式匹配的行(称为 sed 地址)。 -E 告诉 sed 使用 POSIX ERE(扩展正则表达式),我们在这里需要它,因为默认情况下,POSIX BRE(基本正则表达式)没有定义交替运算符。

对于简单过滤(并打印与某些模式匹配的行),grep 也是一个选项(而且是一个非常快速的选项):

grep '#registered\|#subscribed\|#phonever' file

更通用的解决方案(awk 带有模式文件)

更大(可能是动态)模式列表的解决方案是将所有模式保存在单独的文件中,例如 patterns:

#registered
#subscribed
#phonever

并使用此 awk 程序:

awk 'NR==FNR { pat[[=14=]]=1 } NR>FNR { for (p in pat) if ([=14=] ~ p) {print;next} }' patterns file

首先将所有模式加载到 pat 数组中,然后尝试匹配 file 中每一行上的任何模式,打印并前进到下一行找到第一个匹配项。

结果是一样的:

Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever

但脚本现在不会针对每组新模式进行更改。但是请注意,这会带来性能损失(正如一般解决方案通常所做的那样)。对于较短的模式列表和较小的文件,这应该不是问题。


以上的变体要快得多(grep 带有固定字符串模式文件)

基于上面的方法(在文件中保留固定字符串 "patterns" 的列表),我们实际上可以使用 grep —— 它提供了一个专门的选项 (-f FILE) 用于从文件中获取模式,每行一个。为了进一步加快匹配速度,我们还应该使用 -F/--fixed-strings 选项。

所以,这个:

grep -Ff patterns file

将非常快,以最小的内存开销处理长长的固定字符串模式列表和大文件。

简单awk方法:

awk '/#(registered|subscribed|phonever)/' file

输出:

Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever

  • (registered|subscribed|phonever) - 正则表达式交替组匹配几个可能的正则表达式中的单个正则表达式
$ cat tst.awk
NR==FNR {
    strings[[=10=]]
    next
}
{
    for (i=2; i<=NF; i++) {
        if ($i in strings) {
            print
            next
        }
    }
}

$ awk -f tst.awk strings file
Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever

$ cat strings
#registered
#subscribed
#phonever

$ cat file
Name:email:username #registered
Name2:email2:username2
Name3:email3:username3 #registered #subscribed #phonever
Name4:email4:username4 #unconfirmed

如果您的文件很大而您的目标词集相对较小并且执行速度对您很重要,那么您可以这样做以生成这些目标词的每个可能的非空子集的所有可能组合:

$ cat subsets.awk
###################
# Calculate all subsets of a given set, see
# https://en.wikipedia.org/wiki/Power_set

function get_subset(A,subsetNr,numVals, str, sep) {
    while (subsetNr) {
        if (subsetNr%2 != 0) {
            str = str sep A[numVals]
            sep = " "
        }
        numVals--
        subsetNr = int(subsetNr/2)
    }
    return str
}

function get_subsets(A,B,       i,lgth) {
    lgth = length(A)
    for (i=1;i<2^lgth;i++) {
        B[get_subset(A,i,lgth)]
    }
}

###################

# Input should be a list of strings
{
    split([=11=],A)
    delete B
    get_subsets(A,B)
    for (subset in B) {
        print subset
    }
}

.

$ cat permutations.awk
###################
# Calculate all permutations of a set of strings, see
# https://en.wikipedia.org/wiki/Heap%27s_algorithm

function get_perm(A,            i, lgth, sep, str) {
    lgth = length(A)
    for (i=1; i<=lgth; i++) {
        str = str sep A[i]
        sep = " "
    }
    return str
}

function swap(A, x, y,  tmp) {
    tmp  = A[x]
    A[x] = A[y]
    A[y] = tmp
}

function generate(n, A, B,      i) {
    if (n == 1) {
        B[get_perm(A)]
    }
    else {
        for (i=1; i <= n; i++) {
            generate(n - 1, A, B)
            if ((n%2) == 0) {
                swap(A, 1, n)
            }
            else {
                swap(A, i, n)
            }
        }
    }
}

function get_perms(A,B) {
    generate(length(A), A, B)
}

###################

# Input should be a list of strings
{
    split([=12=],A)
    delete B
    get_perms(A,B)
    for (perm in B) {
        print perm
    }
}

.

$ echo '#registered #subscribed #phonever' |
    awk -f subsets.awk |
    awk -f permutations.awk
#registered #subscribed #phonever
#subscribed #phonever #registered
#phonever #subscribed #registered
#phonever #registered #subscribed
#subscribed #registered #phonever
#registered #phonever #subscribed
#phonever
#subscribed
#registered #subscribed
#subscribed #registered
#registered
#registered #phonever
#phonever #registered
#subscribed #phonever
#phonever #subscribed

然后你可以让剩下的处理只是一个简单的哈希查找:

$ echo '#registered #subscribed #phonever' |
    awk -f subsets.awk |
    awk -f permutations.awk |
    awk 'NR==FNR{strings[[=14=]];next} {k=(NF>1?[=14=]:"");sub(/[^ ]+ /,"",k)} k in strings' - file
Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever