내 파일에는 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
출력의 행을 오름차순으로 숫자 정렬) 및 (각 행의 연속 발생 횟수 계산)은 지정된 데이터에 대해 다음 출력을 생성합니다.awk
uniq -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