단어 목록 파일에서 단어 수를 셀 때 발생 순서를 유지하는 방법

단어 목록 파일에서 단어 수를 셀 때 발생 순서를 유지하는 방법

두 개의 파일이 있습니다.

  • file1고유 단어 목록
  • file2여러 문장을 포함

file1각 단어의 발생 횟수를 나열하는 탭으로 구분된 파일을 출력하고 싶습니다.file2 파일 1에 나열된 순서를 유지하면서.

예를 들어:

  • file 1:
    dog 
    apple
    cat
    
  • file 2:
    the dog played with the cat and the cat was white.
    the boy ate the apple.
    
  • 원하는 출력:
    dog 1
    apple 1
    cat 2
    

나는 기존에 시도했다답변커뮤니티에서는 모두 출력을 정렬합니다.

답변1

모든 Unix 시스템의 모든 쉘에서 POSIX awk를 사용하십시오.

$ cat tst.awk
BEGIN { OFS="\t" }
NR==FNR {
    words[NR] = $1
    next
}
{
    $0 = " " $0 " "
    gsub(/[^[:alpha:]]+/,"  ")
    for ( i in words ) {
        word = words[i]
        cnts[word] += gsub(" "word" ","&")
    }
}
END {
    for ( i=1; i in words; i++ ) {
        word = words[i]
        print word, cnts[word]+0
    }
}

$ awk -f tst.awk file1 file2
dog     1
apple   1
cat     2

위의 내용에서는 "단어"가 모두 알파벳 문자이고 일치 항목이 대소문자를 구분하기를 원하거나 예제에서와 같이 입력이 모두 소문자이고 예제에서와 같이 file1의 단어가 고유하다고 가정합니다.

답변2

사용행복하다(이전 Perl_6)

@a다음은 한 파일(배열로 저장됨)의 @b줄을 두 번째 파일(배열로 저장됨)의 줄과 일치시키고 발생 횟수(예: Bagging)를 계산 하는 일반적인 솔루션입니다 .

raku -e 'my  @a =  dir(test => "alphabet.txt").IO.lines.reverse; my @b = $*ARGFILES.lines;  \
         for @a -> $a {@b.grep(/<$a>/).Bag.pairs.say};'  alphabet.txt alphabet.txt

구성 시 Raku에는 위치와 파일 이름이 @a제공됩니다 . 구성 시 명령줄에 하나 이상의 파일을 입력하고 Raku의 동적 변수를 통해 읽습니다.dir()test => "…"@b$*ARGFILES

범용 입력alphabet.txt, 한 줄에 한 글자씩, Raku로 읽은 후 즉시 뒤집어서 "z".."a" 순서로 배열을 배열합니다.

범용 출력alphabet.txt(명령줄에 "a".."z"의 복사본 두 개를 입력하는 경우):

(z => 2)
(y => 2)
(x => 2)
(w => 2)
(v => 2)
(u => 2)
(t => 2)
(s => 2)
(r => 2)
(q => 2)
(p => 2)
(o => 2)
(n => 2)
(m => 2)
(l => 2)
(k => 2)
(j => 2)
(i => 2)
(h => 2)
(g => 2)
(f => 2)
(e => 2)
(d => 2)
(c => 2)
(b => 2)
(a => 2)

return이 array와 동일한 순서를 유지하는 방법 과 Raku가 위 출력을 생성하기 위해 @a호출을 필요로 하지 않는 방법에 유의하세요.sort

my @b = $*ARGFILES.lines.words마지막 으로 OP의 문제를 해결하기 위해 위 코드에서 변경해야 할 것은 my @b = $*ARGFILES.lines.

[탭으로 구분된 출력을 얻으려면 위 코드에서 .put대신 사용하십시오. .say이렇게 하면 주변 대괄호와 =>두 열 사이의 화살표가 제거됩니다.]

최종 코드:

~$ raku -e 'my @a = dir(test => "dog_apple_cat.txt").IO.lines.grep(*.chars);  \
            my @b = $*ARGFILES.lines.words; for @a -> $a {  \
            @b.grep(/<$a>/).Bag.pairs.put};' text.txt
dog 1
apple.  1
cat 2

https://docs.raku.org/type/Bag
https://raku.org

관련 정보