Cómo obtener el número de cada signo de puntuación de un archivo

Cómo obtener el número de cada signo de puntuación de un archivo
grep '[".?!"]'

Devuelve las líneas que tienen uno de estos, pero no tengo idea de cómo saber cuántos hay en cada línea, y mucho menos cuántos ., ? y ! hay.

Respuesta1

Esto imprimirá una lista de todos los caracteres de puntuación que se encuentran en el archivo, un carácter de puntuación por línea, cada uno precedido por el recuento de esos caracteres en el archivo:

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.

Respuesta2

Para encontrar el número total de dichos signos de puntuación en un archivo, puede usar trpara eliminar todos los demás y luego wccontarlos:

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

Respuesta3

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 los totales generales.

Puede pasarle varios nombres de archivos en la línea de comando y se comportará como si hubiera catreunido todos los archivos, pero es bastante fácil modificar este script para procesar cada archivo 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 utilicé para probar este script:

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.

Y aquí está el resultado 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

Respuesta4

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 alguno de [?!.]esos comandos, primero se imprimirá su número de línea, luego el recuento de los caracteres en esa línea y luego un recuento acumulado 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

información relacionada