WhatsApp 문자 채팅 기본 분석: 참가자당 문자 수

WhatsApp 문자 채팅 기본 분석: 참가자당 문자 수

익숙 grep | uniq -c | sort -rn하지만 이 경우는 좀 복잡해요. Whatsapp 웹 채팅을 복사하면 다음과 같은 결과가 나타납니다.

[3:14 pm, 25/09/2020] James Smith: Hello!
[6:42 pm, 25/09/2020] John Doe: hi
[6:43 pm, 25/09/2020] James Smith: I was wondering..
if blah blah
and also blah
[6:45 pm, 25/09/2020] James Smith: blah blah blah blah...

wc -c문자 수()부터 시작하여 대화에 참여한 각 사람에 대한 통계를 얻으려고 합니다 .

 74  James Smith
  2  John Doe

그럼 우리는 어떻게 해야 합니까? 즉, 채팅에 참여한 각 참가자의 텍스트 수입니다. 위의 예에서 Smith는 74자를 제공했고 Doe는 2자를 제공했습니다.

테스트하기 위해 가설에 맞는 WhatsApp 웹 채팅에서 몇 줄을 복사했습니다. 파일에 쉽게 붙여넣으려면: xsel -b > filet_to_test.txt.

유효한 가정:

  • 메시지에는 개행 문자가 포함될 수 있습니다.
  • [6:45 pm, 25/09/2020]두 번째 줄 위에는 문자열을 포함할 수 없습니다 .
  • 새로운 메시지/기록은 어떤 형태로든 [6:45 pm, 25/09/2020]시작될 수 있습니다 ^\[\d{1,2}:\d{2}\s[ap]m,\s\d{2}/\d{2}/\d{4}\]\s.
  • 타임스탬프 뒤의 사용자 이름에는 콜론이 포함되지 않습니다.

보다 이상적인 솔루션은 확장 가능합니다(아마도 다음을 사용하여밀러), 예를 들어 범위 내 또는 각 요일/시간에 대한 문자/단어 수를 가져옵니다.

답변1

@dani-garcia와 비슷한 접근 방식입니다. 먼저 파일을 tab별도의 파일로 문명화하십시오.

cat file | 
  tr "\n" "\000" | 
  sed "s/\x0\[/\n/g" | 
  sed "1 s/\[//; s/\]/\t/1; s/:/\t/2; s/\x0/ /g" |
  sed -E "s/(^[^,]+), ([0-9]{1,2}).([0-9]{2}).([0-9]{4})/\4-\3-\2 \1/" 

2020-09-25 3:14 pm      James Smith     Hello!
2020-09-25 6:42 pm      John Doe        hi
2020-09-25 6:43 pm      James Smith     I was wondering.. if blah blah and also blah
2020-09-25 6:45 pm      James Smith     blah blah blah blah...

tr모든 \newline을 다음으로 번역 하여null

cat file | tr "\n" "\000" | 

그런 다음 패턴이 있는 곳에 sed g전체적으로 ewline을 다시 삽입합니다.\nnull[

sed "s/\x0\[/\n/g" | 

[마지막으로, 줄의 시작 부분을 잃어 개별 줄이 정리됩니다.1

sed "1 s/\[//; 

첫 번째 것을 ab ]로 바꾸십시오.\t

    s/\]/\t/1;

두 번째 것을 ab :로 교체하십시오.\t

    s/:/\t/2;

마지막으로 원래 ewline으로 구분된 단어를 연결하지 않으려면 나머지를 다음 null으로 바꿉니다.\n

    s/\x0/ /g"

날짜를 정리하여 보기 좋게 정렬하세요.

    sed -E "s/(^[^,]+), ([0-9]{1,2}).([0-9]{2}).([0-9]{4})/\4-\3-\2 \1/" 

이제 필드가 분리되었으므로 정렬, 그룹화, 계산 등 원하는 작업을 수행할 수 있습니다.

| awk -F'\t' '{chats[$2]++; words[$2]+=split($3,tmp," "); chars[$2]+=length($3)}
   END{for (who in chats){
     S=(chats[who]==1)?"":"s";
     s=(words[who]==1)?"":"s";
     print who" sent "chats[who]" message"S" with "words[who]" word"s" and "chars[who]" characters"}}'

James Smith sent 3 messages with 14 words and 73 characters
John Doe sent 1 message with 1 word and 2 characters

답변2

각 메시지를 세 부분(날짜, 사람, 메시지)으로 분할한 다음 충족하려는 조건으로 인덱스된 awk 배열을 사용하고 마지막으로 배열의 모든 값을 인쇄할 수 있습니다. 예:

awk '{printf "%s%s", (NR>1&&/^\[.*\]/?"\n":""),$0}END{print " "}' test.txt | sed 's/\(^\[.*\]\) \(.*\): \(.*\)/\1\t\2\t\3/g' | awk 'BEGIN{FS="\t"} {arr[$2] =arr[$2]$3} END{for (i in arr) print length(arr[i]),i}'

test.txt입력 파일 입니다 .

설명하다:

첫 번째 명령( )은 줄이 로 시작하지 않는 경우, 즉 새 메시지가 아니므로 awk '{printf "%s%s", (NR>1&&/^\[.*\]/?"\n":""),$0}END{print " "}' test.txt줄 바꿈을 제거하므로 전체 메시지가 같은 줄에 있게 됩니다.[blahblahblah]

두 번째 명령( sed 's/\(^\[.*\]\) \(.*\): \(.*\)/\1\t\2\t\3/g')은 각 줄을 날짜(패턴 포함 [.*]), 사람(날짜와 콜론 사이), 메시지의 세 부분으로 나눕니다. 그런 다음 각 부분을 탭으로 구분하여 각 줄을 출력합니다.

마지막으로 세 번째 명령( awk 'BEGIN{FS="\t"} {arr[$2] =arr[$2]$3} END{for (i in arr) print length(arr[i]),i}')은 사람별로 색인화된 awk 배열을 가져와서 각 사람에 대한 메시지 연결 길이를 인쇄합니다.

가설

  • 날짜는 사이에 이러한 기호가 있거나 없는 것으로 [구분됩니다 .]
  • 이름에 콜론이 포함되어 있지 않습니다.
  • [6:45 pm, 25/09/2020]메시지에는 새 줄에서 시작되지 않은 것처럼 문자열이 포함될 수 있습니다 .

나는 익숙하지 않다밀러, 그러나 마지막 awk 명령을 변경하여 확장 가능한 원하는 솔루션과 유사한 작업을 수행할 수 있습니다.

아마도 가장 효율적인 접근 방식은 아니지만 작동합니다.

관련 정보