假设你有一个文本文件,比如list.txt
,就像这样:
# Category 1
foobar
# Category 2
dummy1
dummy2
dummy3
# Category 3
foobar.dummy
foobar.dummy
你有一个bash脚本,比如list.sh
,从list.txt
中提取行。该脚本使用一个或多个模式来使用grep过滤文本文件。从概念上讲,它将来自命令行:
cat list.txt | grep filter1 | grep fitler1 | ... | grep filtern
但是,问题是过滤器的数量会有所不同,因此您必须使用循环来进行过滤。对于循环,我希望像下面这样的东西可以工作。
filters=$*
for filter in ${filters[@]}; do
result=`ad_hoc_show $result | grep $filter`
done
ad_hoc_show $result # should maintain original line structure
例如,下面是所需的输出。
$ list.sh foobar
foobar
foobar.dummy
foobar.dummy
$ list.sh dummy \d
dummy1
dummy2
dummy3
那么,关于如何实现ad_hoc_show
函数的任何建议?
答案 0 :(得分:2)
如果您的grep
支持-P
,那么您可以使用此功能:
filt() {
re=$(printf "(?=.*?%s)" "$@")
grep -P "$re" list.txt
}
filt 'dummy' '\d'
dummy1
dummy2
dummy3
filt 'foobar'
foobar
foobar.dummy
foobar.dummy
更新:如果grep -P
不可用,您可以使用awk
:
filt() { re=$(printf "/%s/&&" "$@"); awk "${re:0: -2}" list.txt; }
filt 'dummy' '[0-9]'
dummy1
dummy2
dummy3
filt 'foobar'
foobar
foobar.dummy
foobar.dummy
答案 1 :(得分:1)
这样的事情应该有效:
#!/bin/sh
ad_hoc_show() {
filter=$1
shift
if [ $# -eq 0 ]; then
grep "$filter"
return
fi
grep "$filter" | ad_hoc_show "$@"
}
file=$1
shift
ad_hoc_show "$@" <"$file"
David C. Rankin在评论中指出:
对于bash
,可以通过替换
grep "$filter" | ad_hoc_show "$@"
与
ad_hoc_show "$@" <<<"$(grep "$filter")"
在递归调用中。
使用shift
ad_hoc_show {{1},您可以避免使用偏移数组索引来使用"${@:2}" in the
(我不知道这是否有正式术语) } shift` lines。