터미널에서 파일에 있는 단어의 문자 수를 계산하는 쉬운 방법이 있습니까?

터미널에서 파일에 있는 단어의 문자 수를 계산하는 쉬운 방법이 있습니까?

내 파일에는 1억 줄이 있습니다.

행당 하나의 열만 있습니다.

예를 들어

aaaaa
bb
cc
ddddddd
ee

문자 수를 나열하고 싶습니다.

이와 같이

2 character words - 3
5 character words - 1
7 character words - 1

등.

터미널에서 쉽게 할 수 있는 방법이 있나요?

답변1

$ awk '{ print length }' file | sort -n | uniq -c | awk '{ printf("%d character words: %d\n", $2, $1) }'
2 character words: 3
5 character words: 1
7 character words: 1

첫 번째 awk필터는 이름이 지정된 파일의 각 줄 길이만 인쇄합니다 file. 파일에는 한 줄에 한 단어가 포함되어 있다고 가정합니다.

( sort -n출력의 행을 오름차순으로 숫자 정렬) 및 (각 행의 연속 발생 횟수 계산)은 지정된 데이터에 대해 다음 출력을 생성합니다.awkuniq -c

   3 2
   1 5
   1 7

awk그런 다음 각 줄을 "Y 문자가 있는 X 줄"로 해석하고 원하는 출력을 생성하는 두 번째 스크립트에 의해 구문 분석 됩니다.


awk또 다른 해결책은 모든 작업을 배열로 수행하고 길이 수를 저장하는 것입니다. 효율성, 가독성/이해 용이성(및 유지 관리 용이성) 간의 균형을 맞추는 것이며 어떤 솔루션이 "최고"인지입니다.

대체 솔루션:

$ awk '{ len[length]++ } END { for (i in len) printf("%d character words: %d\n", i, len[i]) }' file
2 character words: 3
5 character words: 1
7 character words: 1

답변2

awk혼자 하는 또 다른 방법

$ awk '{words[length()]++} END{for(k in words)print k " character words - " words[k]}' ip.txt 
2 character words - 3
5 character words - 1
7 character words - 1
  • words[length()]++입력라인의 길이를 키로 하여 카운트 저장
  • END{for(k in words)print k " character words - " words[k]}모든 행이 처리된 후 원하는 형식으로 배열 내용을 인쇄합니다.


성능 비교, 선택한 숫자가 두 실행 중 가장 좋음

$ wc words.txt
 71813  71813 655873 words.txt
$ perl -0777 -ne 'print $_ x 1000' words.txt > long_file.txt
$ du -h --apparent-size long_file.txt
626M    long_file.txt

$ time awk '{words[length()]++} END{for(k in words)print k " character words - " words[k]}' long_file.txt > t1

real    0m20.632s
user    0m20.464s
sys     0m0.108s

$ time perl -lne '$h{length($_)}++ }{ for $n (sort keys %h) {print "$n character words - $h{$n}"}' long_file.txt > t2

real    0m19.749s
user    0m19.640s
sys     0m0.108s

$ time awk '{ print length }' long_file.txt | sort -n | uniq -c | awk '{ printf("%d character words - %d\n", $2, $1) }' > t3

real    1m23.294s
user    1m24.952s
sys     0m1.980s

$ diff -s <(sort t1) <(sort t2)
Files /dev/fd/63 and /dev/fd/62 are identical
$ diff -s <(sort t1) <(sort t3)
Files /dev/fd/63 and /dev/fd/62 are identical

파일에 ASCII 문자만 있는 경우

$ time LC_ALL=C awk '{words[length()]++} END{for(k in words)print k " character words - " words[k]}' long_file.txt > t1

real    0m15.651s
user    0m15.496s
sys     0m0.120s

시간이 perl너무 많이 변하지 않은 이유를 잘 모르겠습니다. 인코딩을 다른 방식으로 설정해야 할 수도 있습니다.

답변3

다음은 perl이에 상응하는 내용입니다(선택 사항 - 정렬 포함).

$ perl -lne '
    $h{length($_)}++ }{ for $n (sort keys %h) {print "$n character words - $h{$n}"}
' file
2 character words - 3
5 character words - 1
7 character words - 1

답변4

대리자하나GNU awk를 호출하려면 다음을 사용하십시오.인쇄 기능:

$ awk 'BEGIN { PROCINFO["sorted_in"] = "@ind_str_asc"}
       {c[length($0)]++}
       END{
           for(i in c){printf("%s character words - %s\n",i,c[i])}
          }' infile
2 character words - 3
5 character words - 1
7 character words - 1

핵심 알고리즘은 단지 배열의 문자 수를 수집합니다. 마지막 부분은 printf 형식으로 수집된 개수를 인쇄합니다.

빠르고 간단하며 awk를 한 번만 호출하면 됩니다.

정확하게 말하면 배열을 유지하는 데 더 많은 메모리가 사용됩니다. 그러나 정렬은 호출되지 않으며(숫자 배열 인덱스는 항상 PROCINFO를 사용하여 정렬을 탐색하도록 설정됨) 외부 프로시저가 여러 개가 아닌
단 하나뿐입니다 .awk

관련 정보