첫 번째 단어에 특정 문자 집합이 포함된 줄 찾기

첫 번째 단어에 특정 문자 집합이 포함된 줄 찾기

입력 파일은 여러 개의 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.

여기서 유일한 비효율성은 관심이 없는 문자의 빈도를 계산한다는 것입니다.

관련 정보