正则表达式匹配尽可能多的字符串

Regex match as many of strings as possible

我不知道这是否可行或有意义,但我想做的是 grepawk 匹配多个字符串的文件,但只显示匹配项匹配最多的字符串。

所以我会有这样的文件:

cat,dog,apple,bark,chair
apple,chair,wall
cat,wall
phone,key,bark,nut
cat,dog,key
phone,dog,key
table,key,chair

我想匹配包含大部分这些字符串的一行:cat|dog|table|key|wall。不一定要包括所有这些,但无论哪一行最匹配,都将其打印出来。

例如,我希望它显示以下输出:

cat,dog,key

因为这是包含正在搜索的大部分字符串的行。

我试过使用:

cat filename \
|egrep -iE 'cat' \
|egrep -iE 'dog' \
|egrep -iE 'table' \
|egrep -iE 'key' \
|egrep -iE 'wall'

但它只会显示显示所有字符串的行,我也试过:

egrep -iE 'cat|dog|table|key|wall' filename

但这会显示与这些字符串中的任何一个匹配的任何行。

正则表达式可以做这样的事情吗?

使用awk,并为每个匹配的单词增加一个计数器。如果计数器高于最高计数,则保存此行。

awk 'BEGIN {max = 0}
     { count=0;
       if (/\bcat\b/) count++;
       if (/\bdog\b/) count++;
       ...
       if (count > max) { saved = [=10=]; max = count; }
     }
    END { print saved; }'
$ awk -F, -v r='^(cat|dog|table|key|wall)$' '{c=0;for (i=1;i<=NF;i++)if ($i~r)c++; if (c>max){max=c;most=[=10=]}} END{print most}' file
cat,dog,key

工作原理

  • -F,

    这会将字段分隔符设置为逗号。

  • -v r='^(cat|dog|table|key|wall)$'

    这会将变量 r 设置为匹配您感兴趣的单词的正则表达式。正则表达式以 ^ 开头,以 $ 结尾。 这确保只有整个单词匹配。

  • c=0;for (i=1;i<=NF;i++)if ($i~r)c++

    这会将变量 c 设置为当前行的匹配项数。

  • if (c>max){max=c;most=[=18=]}

    如果当前行的匹配数 c 超过了先前的最大值 max,则更新 max 并将 most 设置为当前行.

  • END{print most}

    当我们读完文件后,打印包含 most 个匹配项的行。

为了让问题更有趣,我创建了两个输入文件:

InFile1 ...

cat|dog|table|key|wall

InFile2 ...

cat,dog,apple,bark,chair
apple,chair,wall
cat,wall phone,key,bark,nut
cat,dog,key
phone,dog,key
table,key,chair

请注意 InFile2 与原来的不同 post 因为它包含两行,每行包含三个匹配项。 因此,第一名有一个 "tie",两者都是 已报告。

此代码...

 awk -F, '{if (NR==FNR) r=[=12=]; else {count=0
   for (j=1;j<=NF;j++) if ($j ~ r) count++
   a[FNR]=count" matching words in "[=12=]
   if (max<count) max=count}}                     
   END{for (j=1;j<=FNR;j++) if (1==index(a[j],max)) print a[j]}'  \
$InFile1 $InFile2 >$OutFile

... 生成了这个 OutFile ...

3 matching words in cat,dog,key
3 matching words in table,key,dog,banana

丹尼尔·B·马丁