파일의 각 문자로 시작하는 단어 수 계산

파일의 각 문자로 시작하는 단어 수 계산

파일을 가져와 알파벳의 각 문자가 단어 수의 내림차순으로 단어를 시작하는 횟수를 인쇄해야 합니다. 예를 들어, 파일이 다음과 같은 경우:

my nice name is Mike Meller 

그러면 출력은 다음과 같아야 합니다.

3 M
2 N
1 I

이 작업을 한 줄로 수행해야 합니다. wc -m및 와 같은 명령이 있다는 것을 알고 있지만 wc -w각 문자를 반복하고 동일한 방식으로 인쇄한 다음 원하는 방식으로 정렬하는 방법을 잘 모르겠습니다.

답변1

편도... (같은 단어를 두 번 계산하지 않도록 편집됨)

$ echo "my nice name is Mike Meller" | tr ' ' '\n' | sort -f | uniq -i | sed -nr 's/^([a-z]).*/\U\1/Ip' | uniq -c | sort -r
  3 M
  2 N
  1 I
  • tr ' ' '\n'공백을 줄 바꿈으로 변경
  • sort -f대소문자가 다르더라도 동일한 항목이 함께 있도록 행을 정렬합니다.
  • uniq -i중복된 단어를 제거하고 대소문자를 무시하세요.
  • sed -nr 's/^([a-z]).*/\U\1/Ip'첫 번째 문자를 제외한 모든 문자를 제거하고 모든 문자를 대문자로 변경하고 문자로 시작하지 않는 줄을 인쇄하지 마십시오.
  • uniq -c동일한 행 수 계산
  • sort -r내림차순 정렬

( echo "my nice name is Mike Meller"다음으로 교체... cat name-of-your-file)

답변2

그리고 perl:

perl -Mopen=locale -lne '
  $c{uc $_}++ for /\b\p{Alpha}/g;
  END{for (sort {$c{$b} <=> $c{$a}} keys %c) {print "$c{$_} $_"}}'

일부 문자가 분해된 형태로 나타나는지 확인하십시오. 예를 들어, É입력이 사전 결합(U+00E9) 대신(예: E 다음에 U+0301 결합 악센트) 인 경우 사전 결합(U+00E9) 대신 Nor É로 계산됩니다 .EÉ

이것이 문제인 경우 가장 좋은 접근 방식은 먼저 텍스트를 분해하고(일부 문자소에는 미리 구성된 형식이 없기 때문에) 문자소 클러스터를 기반으로 작업하는 것입니다. 어쨌든, 다음과 같이 분해하고 싶은 것이 있습니다 .

비교하다:

$ printf 'my fine name is \uc9ric, maybe E\u301ric, certainly not Eric\n' |
  perl -Mopen=locale -lne '
    $c{uc $_}++ for /\b\p{Alpha}/g;
    END{for (sort {$c{$b} <=> $c{$a}} keys %c) {print "$c{$_} $_"}}'
2 E
2 N
2 M
1 C
1 FI
1 É
1 I

그리고:

$ printf 'my fine name is \uc9ric, maybe E\u301ric, certainly not Eric\n' |
  perl -Mopen=locale -MUnicode::Normalize -lne '
    $c{uc $_}++ for NFKD($_) =~ /\b(?=\p{Alpha})\X/g;
    END{for (sort {$c{$b} <=> $c{$a}} keys %c) {print "$c{$_} $_"}}'
2 É
2 M
2 N
1 E
1 I
1 C
1 F

답변3

GNU awk:

gawk '
  { for (i=1; i<=NF; i++) count[toupper(substr($i,1,1))]++ } 
  END {
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (key in count) print count[key], key
  }
' file 

답변4

이게 숙제가 아니길 바라요? ;-) 까다로운 부분은 Meller의 "L"을 두 번 계산하고 싶지 않다는 것입니다. 그렇죠? 그래서 "독특함"이 있습니다.

$cat t
my nice name is Mike Meller

그런 다음 변환을 수행하는 명령 파이프라인이 제공됩니다.

$tr '[a-z]' '[A-Z]' < t |     # Convert all to upper case
fold -b -w 1 |                # Break into one letter per line
awk -f t.awk |                # Pipe the whole mess to awk to count
sort -r -n                    # Sort in reverse numeric order

awk 스크립트는 별도의 파일로 나누는 것이 가장 좋지만 bash에서는 한 줄에 모두 넣을 수 있습니다.

$cat t.awk    
/ / {                         # Match spaces,
  for (c in wc) {dc[c]+=1}    #  Accumulate word count (wc) into doc count (dc)
  split("",wc)                #  Reset the word count
}

!/ / {                        # Match non-spaces,
  if (wc[$1] == "") wc[$1]=1  #  If haven't already seen char in this word, mark it Donny
}

# Finally, output the count and the letter
END {
  for (c in wc) {dc[c]+=1}    # Accumulate one last time, in case there is no trailing space
  for (c in dc) {print c, dc[c]}
}

(나를 위해) 다음과 같은 출력이 생성됩니다.

$tr '[a-z]' '[A-Z]' < t | fold -b -w 1 | awk -f t.awk  | sort -r -n
4 M
4 E
3 I
2 N
1 Y
1 S
1 R
1 L
1 K
1 C
1 A

관련 정보