Вопрос 1

Вопрос 1

Вопрос 1

я могу использовать

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

чтобы получить вывод, как показано ниже:

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

И я также хочу узнать, сколько совпадений было найдено, поэтому я использую -cопцию, на этот раз я получаю только 26, могу ли я объединить совпавшее содержимое и количество с помощьюgrep встроенныйварианты? Если нет, то как?

вопрос 2

Я нашел решение на Github для ответа на вопрос 1:

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

Но вывод часто странный, который выводится после новогоприглашение оболочки!Почему?

вывод после нового приглашения оболочки

решение1

Вы всегда можете сделать:

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

Или сделать все это так awk(что также позволит избежать -oи \+GNUизмов):

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

или perl:

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

(обратите внимание, что в этом случае \wограничивается буквами ASCII, добавьте , -Mopen=localeчтобы включить любую букву в любом алфавитном сценарии в соответствии с локалью, как в подходах grepили awk(некоторых awk)

Что касается вашего вопроса 2, это потому, что bash(в отличие от zsh) не ждет команд, запущенных в процессе подстановки, вызывая такого рода проблемы. СмотритеВывод замещения процесса не соответствует порядкуБольше подробностей.

решение2

Вместо того, чтобы teeиспользовать такой инструмент, какpee:

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

Если peeон недоступен, это можно сделать с помощью отдельной bashоболочки и отключить ее подсказки с помощью unsetи 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"

Общие ответы:

  1. Невозможно сделать с одним экземпляром grep.

    Чтобы получить полный подсчет, когда в строке есть более одного совпадения grep -o, используйте wc -l:

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

    Выход:

    4
    

    Если требуется префиксное количество, используйте nl, (или cat -n):

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

    Выход:

         1  bar
         2  baz
         3  buz
         4  biz
    
  2. С параллельными процессами,то есть

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

    нет гарантии, какой процесс завершится первым. Иногда можно добавить небольшую задержку, чтобы застраховать заказ.

    Печать параллельно "фу" будет первый "уф" после задержки в 1 секунду:

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

    Печать параллельно "уф" будет первый "фу" после задержки в 1 секунду:

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

Связанный контент