Cómo get el número de cada signo de puntuación de un file

grep '[".?!"]' 

Devuelve las líneas que tienen uno de estos, pero no tengo ni idea de cómo decir cuántos hay en cada línea, y less cuantos,.,? Y! existen.

Esto imprimirá una list de todos los caracteres de puntuación encontrados en el file, un carácter de puntuación por línea, cada uno procedido por el recuento de los caracteres en el file:

 grep -o '[[:punct:]]' file | sort | uniq -c 

Me gusta probar ejecutando / var / log / syslog, el mío tiene más de 150,000 líneas en este momento.

Para encontrar el número total de dichos signos de puntuación en un file, puede usar tr para quitar todos los demás y luego contar:

 tr -dc '.?!' | wc -c 

Aquí hay un script awk que busca líneas que contengan . , ? o ! . Imprime el número de línea de cada línea que contiene cualquiera de esos signos de puntuación, el número encontrado de cada marca, más el número total de marcas en esa línea. Al final de los datos, imprime totales generales.

Puede pasarle varios nombres de file en la command-line y se comportará como si hubiera catueado todos los files juntos, pero es bastante fácil modificar este script para procesar cada file individualmente.

 #!/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 } 

Aquí hay algunos datos aleatorios que usé para probar este script:

 Some test data .a.?? .u o..ru. !!?aarl.?...ts e.?a.eli?.?s.. ?.rst .eale! ti h ..rs. ?er.t. dn!t?.?.l.?t ?.n!rer ed.!???? a .!..a.tit. No punctuation !.an.!isda!.oa!le.d..a.!sh.t? ?!?. ..!i hi...h iii.?..ai hh? .h ru?....t..s !.. a .li?hs !. ia tso???.tr?t .hl..i.aids l.?.? Bye-bye. 

Y aquí está la salida que se generó:

  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 

Probado en GNU Awk 3.1.7

 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 

Para cualquier línea que contenga cualquiera de [?!.] Ese command imprimirá primero su número de línea, luego el recuento de los caracteres en esa línea, y luego un recuento de ejecución para cada uno.

 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