Questão 1

Questão 1

Questão 1

Eu posso usar

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

para obter saída como abaixo:

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()

E também quero saber quantas ocorrências foram correspondidas, então uso -ca opção, desta vez só consigo 26, posso combinar conteúdos e contagens correspondentes comgrep construídas emopções? Se não, como fazer?

Questão 2

Encontrei uma solução no Github para responder à pergunta 1:

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

Mas a saída costuma ser estranha, o que ocorre após um novoprompt de shell!Por que?

saída após um novo prompt do shell

Responder1

Você sempre pode fazer:

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

Ou faça tudo em awk(o que também evitaria os -oGNUismos \+):

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

ou perl:

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

(observe que, nesse caso, \westá limitado a letras ASCII, adicione a -Mopen=localepara incluir qualquer letra em qualquer escrita alfabética de acordo com a localidade, como nas abordagens grepou awk(algumas awk))

Sobre sua pergunta 2, é porque bash(ao contrário de zsh) não espera comandos iniciados na substituição de processos causando esse tipo de problema. VerA saída de substituição do processo está fora de ordempara mais detalhes.

Responder2

Em vez de teeusar uma ferramenta comopee:

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

Se peenão estiver disponível, isso pode ser feito com um bashshell separado e silenciar seus prompts com unsete 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"

Respostas gerais:

  1. Não pode ser feito com uma única instância do grep.

    Para obter uma contagem completa quando há mais de uma correspondência por linha com grep -o, use wc -l:

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

    Saída:

    4
    

    Se uma contagem prefixada for necessária, use nl, (ou cat -n):

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

    Saída:

         1  bar
         2  baz
         3  buz
         4  biz
    
  2. Com processos paralelos,ou seja

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

    não há garantia de qual processo termina primeiro. Às vezes, um pequeno atraso pode ser adicionado para garantir o pedido.

    Imprimir paralelo "foo" primeiro, então "ah" após um atraso de 1 segundo:

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

    Imprimir paralelo "ah" primeiro, então "foo" após um atraso de 1 segundo:

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

informação relacionada