问题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.")
但输出往往很奇怪,是new一个之后的输出外壳提示符!为什么?
答案1
你总是可以这样做:
grep -o ... | awk '{print};END{if (NR) print "\n" NR " matched."}'
或者完成整个事情awk
(这也可以避免-o
和\+
GNUisms):
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
根据区域设置添加 a 以包含任何字母脚本中的任何字母,如grep
或awk
(some 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
不可用,可以使用单独的 shell 来完成,并使用和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"
一般回答:
无法通过 的单个实例完成
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
通过并行进程,IE
tee >(echo -e "\n`wc -l` matched.")
无法保证哪个进程首先完成。有时可以增加一点延迟以确保订单。
打印并行“富“首先,然后”钱币" 延迟 1 秒后:
echo foo | tee >(sleep 1s; rev)
打印并行“钱币“首先,然后”富" 延迟 1 秒后:
echo foo | tee >(rev) >(sleep 1s;cat) > /dev/null