输入文件存在于包含多个 10 个字母组合的行之外:
NGNAEAREAX EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
NCNREDEEEQ EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
我需要一个正则表达式(PCRE 或 BRE/ERE)来查找第一个单词包含形成单词“REGEX”的字母的所有行。因此该行的第一个单词必须至少包含 1 个 R、2 个 E、1 个 G 和 1 个 X。
所以上面的输出将是:
NGNAEAREAX EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
答案1
您不能(*)将其与单个正则表达式匹配。您需要分别测试每个条件(一个 R、两个 E、一个 G、一个 X),并将它们逻辑“与”在一起以获得最终的真或假结果。
例如使用awk
:
$ awk '$1 ~ /R/ && $1 ~ /E.*E/ && $1 ~ /G/ && $1 ~ /X/' inputfile.txt
NGNAEAREAX EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
(*) 好吧,您可以创建一个包含以下替换的正则表达式每一个这五个字母(R、E、G、E 和 X)的可能组合以不同的顺序出现,但这是不切实际的。
顺便说一句,如果您需要不区分大小写的匹配并且您正在使用 GNU awk:
$ awk -v IGNORECASE=1 '$1 ~ /R/ && $1 ~ /E.*E/ && $1 ~ /G/ && $1 ~ /X/' inputfile.txt
或者在没有 GNU awk 的情况下不区分大小写:
$ awk '$1 ~ /[Rr]/ && $1 ~ /[Ee].*[Ee]/ && $1 ~ /[Gg]/ && $1 ~ /[Xx]/' inputfile.txt
答案2
使用乐(以前称为 Perl_6)
~$ raku -e 'for lines() {my %h; for .words.[0].comb() { %h{$_}++ }; \
.put if %h.keys.contains( "R" & "E" & "G" & "X") && %h<E> >= 2 };' file
输入示例:
NGNAEAREAX EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
NCNREDEEEQ EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
示例输出:
NGNAEAREAX EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
Raku 是 Perl 家族的一种编程语言。发布的问题似乎确实是一个键/值问题,Raku 非常适合它(注意:解决方案中没有正则表达式)。
简而言之,lines
读入时,每行在空白处用 分隔,并取出words
第一个单词。[0]
第一个单词被comb
编辑成单独的字母。
从这一点开始,每个字母都被输入到(之前声明的)%h
散列中,随后该字母(由主题变量 表示$_
)立即成为散列中的唯一字母,其值由已看到的key
次数确定(因此加上-加)。key
%h{$_}++
%h
在代码中返回此时的哈希值(使用say %h.sort
),您将看到以下内容:
(A => 3 E => 2 G => 1 N => 2 R => 1 X => 1)
(C => 1 D => 1 E => 4 N => 2 Q => 1 R => 1)
顶部代码解决方案的最终语句要求%h
散列contains
每个字母"R" & "E" & "G" & "X"
作为键,并且散列的“ E
”键的值为>= 2
。如果找到,则返回整行(.put
缩写为$_.put
,其中$_
代表输入行)。
https://docs.raku.org/language/hashmap
https://perlgeek.de/blog-en/perl-5-to-6/08-junctions.html
https://raku.org
答案3
您可以为此使用前瞻运算符:
grep -P '^\s*+(?=\S*R)(?=\S*E\S*E)(?=\S*G)(?=\S*X)'
在这里寻找:
^
匹配在行的开头\s*+
跳过(并且不回头)所有前导空格(如果有)(?=\S*R)
向前查看此位置是否有R
以下任意数量的非空白字符。(?=\S*E\S*E)
向前查看同一位置的非空白E
non-whitespacesE
。- 你明白了。
答案4
这里有awk
一个函数,可以计算任何单词的字符数,并首先使用该函数来处理查询单词(“REGEX”),然后处理输入的第一个字段中的每个单词。然后,它检查第一个字段单词中的字符数是否足以生成查询单词,如果是,则打印该单词。
awk -v word="REGEX" '
function calc(w,a) {
for (i = 1; i <= length(w); ++i) a[substr(w,i,1)]++
}
BEGIN {
# Character frequencies of the query word are stored in q.
calc(word,q)
}
{
# Get character frequencies for $1 and see if any
# frequency in q are higher. If so, next.
delete f; calc($1,f)
for (ch in q) if (f[ch] < q[ch]) next
print $1
}' file
在问题的输入上运行它会输出NGNAEAREAX
.
这里唯一的低效率是我们计算我们不感兴趣的字符的频率。