버전 2 확인

버전 2 확인

제가 검색을 잘못한 것일지도 모른다고 생각했지만 아무런 답도 찾지 못했습니다. 중복된 내용이 있으면 알려주시면 삭제하겠습니다.

문제 배경

나는 ack(협회), Perl 5를 내부적으로 사용하여 n-그램, 특히 고차 n-그램을 얻습니다. 내가 아는 구문(기본적으로 가장 많이 $9)을 사용하면 최대 9g까지 얻을 수 있지만 10g은 얻을 수 없습니다. 사용하면 접미사 가 $10제공됩니다 . 그런 식으로 문제가 해결되지 않았습니다 . 그래요$10$(10)${10}아니요Language Modeling Toolkit을 사용하는 솔루션에 관심이 있어 ack.

내가 사용한 데이터 세트 중 하나는 Mark Twain의 전체 컬렉션이었습니다.

( wget http://www.gutenberg.org/cache/epub/3200/pg3200.txt && mv pg3200.txt TWAIN_Mark_complete_orig.txt).

나는 내용을 분석했습니다 (참조댓글 분석게시물 끝에) 구문 분석된 결과를 TWAIN_Mark_complete_parsed.txt.

2-gram에서 얻은 결과는 괜찮습니다. 코드와 부분 결과는 다음과 같습니다.

time cat TWAIN_Mark_complete_parsed.txt | \
    ack '(\S+) +(?=(\S+) +)' \
    --output '$1 $2' | \
    sort | uniq -c | \
    sort -rn > Twain_2grams.txt
## `time` info not shown
$ head -n 2 Twain_2grams.txt
  18176 of the
  13288 in the

최대 9g까지,

time cat TWAIN_Mark_complete_parsed.txt | \
    ack '(\S+) (?=(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+))' \
    --output '$1 $2 $3 $4 $5 $6 $7 $8 $9' | \
    sort | uniq -c | sort -rn > Twain_9grams.txt
## time info not shown
$ head -n 2 Twain_9grams.txt
     17 to mrs jane clemens and mrs moffett in st
     17 mrs jane clemens and mrs moffett in st louis

ack( 단지 각 명령을 입력하는 대신 명령을 메타프로그래밍했다는 점에 유의하세요 .)

질문/내가 시도한 것

처음으로 10g을 시도했을 때 결과는 다음과 같았습니다.

time cat TWAIN_Mark_complete_parsed.txt | \
    ack '(\S+) (?=(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+))' \
    --output '$1 $2 $3 $4 $5 $6 $7 $8 $9 $10' | \
    sort | uniq -c | sort -rn > Twain_10grams.txt

$ head -n 2 Twain_10grams.txt
     17 to mrs jane clemens and mrs moffett in st to0
     17 mrs jane clemens and mrs moffett in st louis mrs0

무슨 일이 일어나고 있는지 더 잘 이해하기 위해,

diff -u <(head -n 2 Twain_10grams.txt) <(head -n 2 Twain_9grams.txt) 색상 차이 강조 |

보다이 답변(그리고이 댓글) 단어별 차이 강조 표시를 통해 색상 차이를 자세히 알아보는 방법을 알아보세요. 기본적으로 apt여전히 yumfor colordiff, 그리고 pipfor diff-highlight.

$(10)대신 사용하면 $10처음 두 줄의 출력이 제공됩니다.

     17 to mrs jane clemens and mrs moffett in st $(10)
     17 mrs jane clemens and mrs moffett in st louis $(10)

(2분 후).

${10}대신 사용하면 $10처음 두 줄의 출력이 제공됩니다.

     17 to mrs jane clemens and mrs moffett in st ${10}
     17 mrs jane clemens and mrs moffett in st louis ${10}

그것이 내 생각이 끝나는 곳입니다.

예상/원하는 출력

있습니다.통계(매우실제 출력이 여기에 표시된 출력과 다를 가능성(0이 아니고 유한)이 있습니다. 9-gram에 대한 처음 두 결과는 서로 다른 단어 순서가 아닙니다. 가장 일반적인 10그램의 다른 가능한 부분은 가장 일반적인 9그램 상위 10개를 살펴보면서 찾을 수 있습니다 . head대신 사용하세요. head -n 2그럼에도 불구하고 이것이 우리가 가장 일반적인 두 가지 10g을 가지고 있다는 것을 보장하지는 않는다고 확신합니다. 하지만 제가 이루고 싶은 것이 무엇인지 명확하게 표현할 수 있었으면 좋겠습니다.

17 to mrs jane clemens and mrs moffett in st louis
3 mrs jane clemens and mrs moffett in st louis honolulu

편집하다예상 출력을 (아마도 실제 출력이 아니라 이전에 사용했던 간단한 모델의 출력)로 변경하는 또 다른 세트를 찾았습니다.

     17 to mrs jane clemens and mrs moffett in st louis
      7 happiness in his home had been wounded and bruised almost

head -n 2이것은 내가 얻은 결과를 보여주기 위해 항상 사용하는 것 입니다 .

나는 그것을 얻기 위해 여기에서 사용할 것과 동일한 과정을 겪고 싶지 않습니다.

$ grep -o "to mrs jane clemens and mrs moffett in st [^ ]\+" \
   TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
     17 to mrs jane clemens and mrs moffett in st louis

$ grep -o "mrs jane clemens and mrs moffett in st louis [^ ]\+" \
   TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
      3 mrs jane clemens and mrs moffett in st louis honolulu
      2 mrs jane clemens and mrs moffett in st louis san
      2 mrs jane clemens and mrs moffett in st louis no
      2 mrs jane clemens and mrs moffett in st louis 224
      1 mrs jane clemens and mrs moffett in st louis wash
      1 mrs jane clemens and mrs moffett in st louis wailuku
      1 mrs jane clemens and mrs moffett in st louis virginia
      1 mrs jane clemens and mrs moffett in st louis the
      1 mrs jane clemens and mrs moffett in st louis sept
      1 mrs jane clemens and mrs moffett in st louis on
      1 mrs jane clemens and mrs moffett in st louis hartford
      1 mrs jane clemens and mrs moffett in st louis carson

편집하다새로운 2위 빈도를 찾는 데 사용되는 코드는 다음과 같습니다.

$ grep -o "[^ ]\+ happiness in his home had been wounded and bruised" TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
      6 shelley's happiness in his home had been wounded and bruised
      1 his happiness in his home had been wounded and bruised
$ grep -o "shelley's happiness in his home had been wounded and [^ ]\+" TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
      6 shelley's happiness in his home had been wounded and bruised
$ grep -o "happiness in his home had been wounded and bruised [^ ]\+" TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
      7 happiness in his home had been wounded and bruised almost
$ grep -o "in his home had been wounded and bruised almost [^ ]\+" TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
      7 in his home had been wounded and bruised almost to
$ grep -o "his home had been wounded and bruised almost to [^ ]\+" TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
      7 his home had been wounded and bruised almost to death
$ grep -o "home had been wounded and bruised almost to death [^ ]\+" TWAIN_Mark_complete_parsed.txt | sort | uniq -c | sort -rn
      1 home had been wounded and bruised almost to death thirdly
      1 home had been wounded and bruised almost to death secondly
      1 home had been wounded and bruised almost to death it
      1 home had been wounded and bruised almost to death fourthly
      1 home had been wounded and bruised almost to death first
      1 home had been wounded and bruised almost to death fifthly
      1 home had been wounded and bruised almost to death and

댓글에서 편집

@이니안님 정말 수고하셨어요논평:

이는 릴리스 노트에 설명되어 있습니다.github.com/beyondgrep/ack3/blob/dev/RELEASE-NOTES.md-이제 $1 ~ $9, $, $., $&, $`, $' 및 $+_ 변수만 사용할 수 있습니다.

~을 위한미래의 사람들, 하나 넣고 싶어요버전, 오늘 보관됨, 의RELEASE-NOTES

man페이지에는 ack다음 줄이 있습니다.

$1 through $9
The subpattern from the corresponding set of capturing parentheses.
If your pattern is "(.+) and (.+)", and the string is "this and that',
then $1 is "this" and $2 is "that".

하지만 더 높은 숫자를 얻을 수 있는 방법이 있었으면 좋겠어요. 에서 나오는 정보에 따르면 RELEASE-NOTES그 희망은 크게 무너진 것 같습니다.

하지만ack, "표준" *NIX 유형 터미널 도구를 사용하거나 이를 사용하여 해결 방법이나 해킹을 수행하는 사람이 있는지 여전히 궁금합니다. 내 취향은 순서대로 perl,,,, 입니다. 비슷한 것이 있는 경우(예: 명령줄 구문 분석,grepawksedack아니요NLP 툴킷 기반 솔루션), 저는 이것에도 관심이 있습니다.

나는 이것을 새로운 질문으로 묻는 것이 가장 좋다고 생각합니다. 여기에 답변해주시면 좋을 것 같습니다. 새로운 질문을 게시하게 되면 여기에 링크를 추가하겠습니다.현재 이것은 동일한 질문에 대한 링크일 뿐입니다..


댓글 분석

N-그램 분석을 위해 내 코퍼스를 준비하기 위한 구문 분석은 다음과 같습니다.

tr [:upper:] [:lower:] < TWAIN_Mark_complete_orig.txt | \
# upper case to lower case and avoid useless use of cat
 tr '\n' ' ' | \
# newlines into spaces, so we can later make it one line, single-spaced
 sed -E "s/[^a-z0-9 '*-]+//g" | \
# get rid of everything but letters, numbers, and a few other symbols (corpus)
 awk '{$0=$0;$1=$1}1' > TWAIN_Mark_complete_parsed.txt && \
# collapse all multiple spaces to one space (includes tabs), save to output
:

예, 이 모든 내용은 한 줄에 표시될 수 있습니다(후행 없이 && :). 하지만 이렇게 하면 내가 지금 하고 있는 일을 왜 하고 있는지 읽고 설명하기가 더 쉬워집니다.


시스템 세부정보

$ uname -a
CYGWIN_NT-10.0 MY_MACHINE 3.0.7(0.338/5/3) 2019-04-30 18:08 x86_64 Cygwin
$ bash --version | head -n 1
GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin)
$ ack --version | head -n 2
ack v3.3.1 (standard build)
Running under Perl v5.26.3 at /usr/bin/perl.exe
$ systeminfo | sed -n 's/^OS\ *//p'
Name:                   Microsoft Windows 10 Enterprise
Version:                10.0.17134 N/A Build 17134
Manufacturer:           Microsoft Corporation
Configuration:          Member Workstation
Build Type:             Multiprocessor Free

답변1

나는 Perl 전문가는 아니지만 여기에 가능한 해킹이 있습니다. 올인원 같은데소스 파일, 출력 문자열에서 단일 문자 ack만 처리하는 것 같습니다 . $여러 문자를 허용하도록 이를 변경하면 확실히 작동하지만 간단하게 유지하려면 를 사용할 수 있습니다 0..9. 예를 들어, and as 및 ( 로 표시됨 ) abc...을 허용하도록 변경했습니다.$a$b$10$11diff -u

@@ -188,7 +188,7 @@
         $opt_output =~ s/\\r/\r/g;
         $opt_output =~ s/\\t/\t/g;
 
-        my @supported_special_variables = ( 1..9, qw( _ . ` & ' +  f ) );
+        my @supported_special_variables = ( 1..9, qw( a b _ . ` & ' +  f ) );
         @special_vars_used_by_opt_output = grep { $opt_output =~ /\$$_/ } @supported_special_variables;
 
         # If the $opt_output contains $&, $` or $', those vars won't be
@@ -924,6 +924,8 @@
                 # on them not changing in the process of doing the s///.
 
                 my %keep = map { ($_ => ${$_} // '') } @special_vars_used_by_opt_output;
+                $keep{a} = $10;
+                $keep{b} = $11;
                 $keep{_} = $line if exists $keep{_}; # Manually set it because $_ gets reset in a map.
                 $keep{f} = $filename if exists $keep{f};
                 my $special_vars_used_by_opt_output = join( '', @special_vars_used_by_opt_output );

그러나 10번째 일치 항목만 원하는 경우 $+다음과 같이 사용할 수 있습니다.마지막으로 성공한 검색 패턴의 마지막 대괄호와 일치하는 텍스트.

답변2

세 가지 대체 솔루션:

버전 2 확인

ack 버전 2에서는 변수 $10 $11등이 유효한 것 같습니다.

$ echo 'abcdefghijklmn' | 
  ack '(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)' \
  --output '$1 $2 $3 $11'

a b c k

$ ack --version
ack 2.24
Running under Perl 5.28.1 at /usr/bin/perl

그중에서도 얻으려면겹치는문자열은 다음과 같습니다:

echo 'abcdefghijklmn' |
    ack '(.)(?=(.)(.)(.)(.)(.)(.)(.)(.)(.)(.))' \
    --output '$1 $2 $3 $11'
a b c k
b c d l
c d e m
d e f n

펄5

그러나 다음을 통해 Perl에서 직접 동일한 작업을 수행할 수 있습니다.

echo 'abcdefghijklmn' | 
    perl -ne 'while($_ =~ /(.)(?=(.)(.)(.)(.)(.)(.)(.)(.)(.)(.))/g ){
        print $1," ",$2," ",$11," ","\n" }'
a b k
b c l
c d m
d e n

따라서 단어를 찾아 인쇄하려면(하나 이상의 공백으로 구분):

echo "word1 word2 word3 word4 word5 word6" |
    perl -ne 'while($_ =~ /(\S+) +(?=(\S+) +(\S+) +(\S+))/g ){$,=" ";print $1,$2,$3,$4,"\n" }'

word1 word2 word3 word4 
word2 word3 word4 word5 
word3 word4 word5 word6

인쇄된 줄에는 뒤에 공백이 있습니다(상관하지 않기를 바랍니다).

펄6

:ov또는 (겹침) 수정자를 사용하여 Perl6(Raku)을 사용해 볼 수도 있습니다.

echo "one two three four five" | 
    perl6 -ne 'my @var = $_.match(/ <|w> \w+ [" "+ \w+]**2 <|w> /, :ov); say @var.join("\n") ;'

one two three
two three four
three four five

단일 숫자를 변경하면 다른 개수도 일치됩니다.

echo "one two three four five" | 
perl6 -ne 'my @var = $_.match(/ <|w> \w+ [" "+ \w+]**3 <|w> /, :ov); say @var.join("\n") ;'

one two three four
two three four five

결과

Perl5를 사용하면 결과는 다음과 같습니다.

perl -ne 'while($_ =~ /(\S+) +(?=(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+))/g ){
 $,=" ";
 print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,"\n" 
}' TWAIN_Mark_complete_parsed.txt | 
    sort | 
    uniq -c | 
    sort -rn >Twain_10grams5.txt

Perl6은 이러한 대규모 테스트 텍스트를 완료할 수 없습니다(메모리가 너무 많음)(Perl6은 아직 너무 새롭습니다). ack를 사용하는 것은 perl5보다 훨씬 느리지만 파일은 동일합니다.

head -n 10 Twain_10grams5.txt
     17 to mrs jane clemens and mrs moffett in st louis 
      8 ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- 
      7 in his home had been wounded and bruised almost to 
      7 his home had been wounded and bruised almost to death 
      7 happiness in his home had been wounded and bruised almost 
      6 shelley's happiness in his home had been wounded and bruised 
      5 was by the social fireside in the time of the 
      5 thing indeed if you would like to listen to it 
      5 laughable thing indeed if you would like to listen to 
      5 it was in this way that he found out that

관련 정보