익숙 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
모든 \n
ewline을 다음으로 번역 하여null
cat file | tr "\n" "\000" |
그런 다음 패턴이 있는 곳에 sed
g
전체적으로 ewline을 다시 삽입합니다.\n
null[
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 명령을 변경하여 확장 가능한 원하는 솔루션과 유사한 작업을 수행할 수 있습니다.
아마도 가장 효율적인 접근 방식은 아니지만 작동합니다.