
grep '[".?!"]'
Возвращает строки, в которых есть один из этих символов, но я понятия не имею, как определить, сколько их в каждой строке, не говоря уже о том, сколько там символов ., ? и !.
решение1
Это выведет список всех знаков препинания, найденных в файле, по одному символу препинания на строку, каждый из которых будет подсчитан по количеству этих символов в файле:
grep -o '[[:punct:]]' file | sort | uniq -c
Мне нравится проводить тестирование, запуская /var/log/syslog, у меня сейчас более 150 000 строк.
решение2
Чтобы найти общее количество таких знаков препинания в файле, можно использовать функцию, tr
чтобы отбросить все остальные, а затем wc
подсчитать:
tr -dc '.?!' | wc -c
решение3
Вот скрипт awk, который ищет строки, содержащие .
, ?
или !
. Он выводит номер каждой строки, содержащей любой из этих знаков препинания, количество найденных знаков и общее количество знаков в этой строке. В конце данных он выводит общие итоги.
Вы можете передать ему несколько имен файлов в командной строке, и он будет вести себя так, как будто вы cat
объединили все файлы вместе, но этот скрипт довольно легко модифицировать для обработки каждого файла по отдельности.
#!/usr/bin/awk -f
# Count punctuation marks
# See http://unix.stackexchange.com/q/239894/88378
# Written by PM 2Ring 2015.10.131
BEGIN{
FS = ""
punc = ".?!"
fmt = "%5s: .=%s, ?=%s, !=%s, all=%s\n"
}
/[.?!]+/{
#print NR, $0, NF
count[1] = count[2] = count[3] = 0
for(i=1; i<=NF; i++)
{
n = index(punc, $i)
if(n)
count[n] += 1
}
all = count[1] + count[2] + count[3]
printf fmt, NR, count[1], count[2], count[3], all
for(i=1; i<=3; i++)
total[i] += count[i]
}
END{
all = total[1] + total[2] + total[3]
printf fmt, "Total", total[1], total[2], total[3], all
}
Вот некоторые случайные данные, которые я использовал для тестирования этого скрипта:
Some test data
.a.?? .u o..ru. !!?aarl.?...t s
e.?a.eli?.?s.. ?.r. s.t .e.a.le!
ti h ..rs. ?er.t. dn!t?.?.l.?t
?.n!rer e. d..!???? a .!..a.tit.
No punctuation
!.a.n..!isda!.o a!le.d..a.!sh.t?
?!?. ..!i hi...h iii.?..a i hh?
.h r.u?....t..s !.. a .li?hs !.
ia tso???.tr?t .hl..i.aids l.?.?
Bye-bye.
И вот что получилось на выходе:
2: .=10, ?=4, !=2, all=16
3: .=11, ?=4, !=1, all=16
4: .=8, ?=4, !=1, all=13
5: .=9, ?=5, !=3, all=17
7: .=10, ?=1, !=5, all=16
8: .=9, ?=4, !=2, all=15
9: .=12, ?=2, !=2, all=16
10: .=7, ?=6, !=0, all=13
11: .=1, ?=0, !=0, all=1
Total: .=77, ?=30, !=16, all=123
Протестировано на GNU Awk 3.1.7
решение4
sed -e'1{x;s/^/0ddsQsEsD[q]sq/p;x;}' \
-e'/[^?!.]*\([?!.]\)[^?!.]*/!d;=' \
-e's// l\11+s\1 /g;s/.*/pc0dds?s!s.&Q?E!D./' \
-e's/\([QED]\)\(.\)/[l\21>q9P[\2=]Pl\2pl\1+9P[Total: ]Pps\1]x/g' |dc
Для любой строки, содержащей что-либо из [?!.]
этого, команда сначала выведет ее номер строки, затем количество символов в этой строке, а затем текущий подсчет для каждого символа.
printf %s\\n \? \?\!. '' hey \? '' '' \! ...hey... .\!\? |
sed -e'1{x;s/^/0ddsQsEsD[q]sq/p;x;}' \
-e'/[^?!.]*\([?!.]\)[^?!.]*/!d;=' \
-e's// l\11+s\1 /g;s/.*/pc0dds?s!s.&Q?E!D./' \
-e's/\([QED]\)\(.\)/[l\21>q9P[\2=]Pl\2pl\1+9P[Total: ]Pps\1]x/g' |dc
1
?=1
Total: 1
2
?=1
Total: 2
!=1
Total: 1
.=1
Total: 1
5
?=1
Total: 3
8
!=1
Total: 2
9
.=6
Total: 7
10
?=1
Total: 4
!=1
Total: 3
.=1
Total: 8