입력 파일은 여러 개의 10자 조합을 포함하는 줄 외부에 존재합니다.
NGNAEAREAX EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
NCNREDEEEQ EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
첫 번째 단어에 "REGEX"라는 단어를 구성하는 문자가 포함된 모든 줄을 찾으려면 정규식(PCRE 또는 BRE/ERE)이 필요합니다. 따라서 줄의 첫 번째 단어에는 최소한 R 1개, E 2개, G 1개, X 1개가 포함되어야 합니다.
따라서 위의 결과는 다음과 같습니다.
NGNAEAREAX EAHVSELYCI FNWGNLACQM AWKLRMDHIT PRYMFNYMVM
답변1
단일 정규 표현식과 일치시킬 수 없습니다(*). 최종 참 또는 거짓 결과를 얻으려면 각 조건(R 1개, E 2개, G 1개, X 1개)을 별도로 논리적으로 AND하여 함께 테스트해야 합니다.
예를 들어 다음을 사용합니다 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/언어/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
공백이 아닌 부분을 살펴보세요E
.- 당신은 이해했습니다.
답변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
.
여기서 유일한 비효율성은 관심이 없는 문자의 빈도를 계산한다는 것입니다.