我有 2 个文件:args
和text
.例如:
args: [包含脚本的参数]
life
happy
horse
文本:
The horse has a happy life.
Life is fun.
Kids are happy.
我需要一个命令来打印text
包含 中所有模式的行args
。在这种情况下:The horse has a happy life.
答案1
git grep
这是使用的语法git grep
使用布尔表达式组合多个模式:
git grep -e "life" --and -e "happy" --and -e "horse"
上面的命令将立即打印匹配所有模式的行。
如果文件不受版本控制,请添加--no-index
参数。
搜索当前目录中不受 Git 管理的文件。
检查man git-grep
寻求帮助。
grep
通常grep
使用-f
参数将打印至少具有一种模式的行,例如
grep -f args.txt file.txt
在你的情况下它不会起作用。
因此,要同时打印匹配所有模式的行,您可以尝试以下命令:
while read n text; do [ $n -eq $(wc -l < args.txt) ] && echo $text; done < <(while read patt; do grep "$patt" text.txt; done < args.txt | sort | uniq -c)
解释:
- 内部循环将打印与使用文件中的模式列表
while
中的至少一个模式匹配的所有行。text.txt
args.txt
- 然后对该列表进行排序 (
sort
) 并计算出现次数 (uniq -c
)。 - 外
while
循环将仅打印出现次数与其中模式数相同的行args.txt
(即 3)。
另一种方法是删除与至少一个模式不匹配的所有行。
以下是使用 Ex/Vim 编辑器就地更改文件的解决方案:
while read patt; do ex +"v/$patt/d" -scwq text.txt; done < args.txt
注意:这将从文件本身中删除不需要的行。
这是较短的版本,仅在屏幕上打印结果:
ex $(xargs -I% printf "+v/%/d " < args.txt) +%p -scq! text.txt
更改+%p -scq!
为-scwq
将其就地保存到文件中。
这是通过定义 shell 别名的解决方案:
alias grep-all="</dev/stdin $(xargs printf '|grep "%s"' < args.txt)"
使用示例:
grep-all file.txt
有关的:
答案2
使用awk
。
~$ cat textlist.txt | awk '/life/ && /happy/ && /horse/ { print; }'
The horse has a happy life
textlist.txt 是您给出的句子列表。
答案3
您可以使用agrep
来应用和手术。不幸的是它不能应用和文件中的模式列表,因此您必须首先将其扩展为命令参数。
patterns=$(sed 's/;/\\;/' <args | tr '\n' ';' | sed 's/;$//')
agrep "$patterns" text
生成模式列表的修改用分号将它们连接在一起。但是,我们不能在列表末尾有分号,这样它就会被删除,并且任何已经包含分号的模式都必须对该字符进行转义,这样它就不会被视为和操作员。用于echo "$patterns"
查看args
文件是如何转换的。
答案4
也许这不是最有效的方法,但它似乎有效:
# for a in $(cat args); do regex="$regex | grep '$a'"; done
# eval cat text "$regex"
The horse has a happy life.