Pregunta 1

Pregunta 1

Pregunta 1

Puedo usar

grep -o '^[[:alpha:]_]\+[[:blank:]]*([[:blank:]]*)' /etc/rc.d/init.d/functions

para obtener un resultado como el siguiente:

systemctl_redirect ()
checkpid()
__kill_pids_term_kill_checkpids()
__kill_pids_term_kill()
__pids_var_run()
__pids_pidof()
daemon()
killproc()
pidfileofproc()
pidofproc()
status()
echo_success()
echo_failure()
echo_passed()
echo_warning()
update_boot_stage()
success()
failure()
passed()
warning()
action()
strstr()
is_ignored_file()
is_true()
is_false()
apply_sysctl()

Y también quiero saber cuántas apariciones han coincidido, así que uso -cla opción, esta vez solo obtengo 26, ¿puedo combinar contenidos coincidentes y recuentos congrep incorporadoopciones? Si no, ¿cómo?

Pregunta 2

Encontré una solución en Github para responder la Pregunta 1:

grep -o '^[[:alpha:]_]\+[[:blank:]]*([[:blank:]]*)' /etc/rc.d/init.d/functions \
| tee >(echo -e "\n`wc -l` matched.")

Pero el resultado suele ser extraño, ya que se genera después de una nuevaindicador de shell!¿Por qué?

salida después de un nuevo indicador de shell

Respuesta1

Siempre puedes hacer:

grep -o ... | awk '{print};END{if (NR) print "\n" NR " matched."}'

O hacer todo en awk(lo que también evitaría los GNUismos -oy \+):

awk 'match($0, /^[[:alpha:]_]+[[:blank:]]*\([[:blank:]]*\)/) {
       print substr($0, RSTART, RLENGTH)
       n++
     }
     END{if (n) print "\n" n " matched.")'

o perl:

perl -lne 'for (/^\w+\h*\(\h*\)/g) {print; $n++}
           END {print "\n$n matched." if $n}'

(tenga en cuenta que en ese caso \westá limitado a letras ASCII, agregue a -Mopen=localepara incluir cualquier letra en cualquier escritura alfabética según la configuración regional, como en los enfoques grepo awk(algunos awk))

Acerca de su pregunta 2, eso se debe a que bash(a diferencia de zsh) no espera a que se inicien los comandos en la sustitución del proceso, lo que causa este tipo de problema. VerLa salida de sustitución del proceso está fuera de orden.para más detalles.

Respuesta2

En lugar de teeutilizar una herramienta comopee:

grep -o '^[[:alpha:]_]\+[[:blank:]]*([[:blank:]]*)' /etc/rc.d/init.d/functions | 
pee cat 'sleep 1; echo -e "\n`wc -l` matched."'

Si peeno está disponible, se puede hacer con un bashshell separado y silenciar sus indicaciones con unsety shopt:

bash -c \
    "unset PS0 PS1 PS2 PS3
     shopt -u promptvars
     grep -o '^[[:alpha:]_]\+[[:blank:]]*([[:blank:]]*)' \
          /etc/rc.d/init.d/functions |
     tee >( sleep 1s; printf '\n%s matched.' `wc -l`; )
     sleep 2s"

Respuestas generales:

  1. No se puede hacer con una sola instancia de grep.

    Para obtener un recuento completo cuando hay más de una coincidencia por línea grep -o, utilice wc -l:

    printf "foo bar baz\nbuz biz\n" | grep -o 'b[^ ]*' | wc -l
    

    Producción:

    4
    

    Si se necesita un recuento con prefijo, utilice nl, (o cat -n):

    printf "foo bar baz\nbuz biz\n" | grep -o 'b[^ ]*' | nl
    

    Producción:

         1  bar
         2  baz
         3  buz
         4  biz
    
  2. Con procesos paralelos,es decir

    tee >(echo -e "\n`wc -l` matched.")
    

    No hay garantía de qué proceso finaliza primero. A veces se puede añadir un pequeño retraso para asegurar el pedido.

    Imprimir paralelo "foo" primero luego "uf"después de un retraso de 1 segundo:

    echo foo | tee >(sleep 1s; rev)
    

    Imprimir paralelo "uf" primero luego "foo"después de un retraso de 1 segundo:

    echo foo | tee >(rev) >(sleep 1s;cat) > /dev/null
    

información relacionada