0

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

列表示例:

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
4

3 回答 3

3

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

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

下面的部分/.../称为awk模式,对于匹配的行,它执行后面的操作(as { ... })。但由于默认操作是:({ print $0 }打印完整的输入记录/行),因此无需在此处指定。

同样,sed您可以说:

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

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

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

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

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

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

#registered
#subscribed
#phonever

并使用这个awk程序:

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

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

结果是一样的:

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

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


以及上述更快的变体(grep使用固定字符串模式文件)

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

所以这:

grep -Ff patterns file

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

于 2017-08-06T20:22:37.170 回答
0
$ cat tst.awk
NR==FNR {
    strings[$0]
    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($0,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($0,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[$0];next} {k=(NF>1?$0:"");sub(/[^ ]+ /,"",k)} k in strings' - file
Name:email:username #registered
Name3:email3:username3 #registered #subscribed #phonever
于 2017-08-07T01:04:25.517 回答
0

简单的awk方法:

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

输出:

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

  • (registered|subscribed|phonever)- 正则表达式交替组匹配几个可能的正则表达式中的单个正则表达式
于 2017-08-06T20:23:21.557 回答