我有这样的字符串:"thisissometext"。我想在给定目录中(递归地)找到包含这个字符串的所有文本文件,或者它的任何变体,中间有空格和/或换行符。例如,一个文本文件包含"this is sometext",或者"this\n issometext","this\n isso metext" 应在搜索中。我怎样才能做到这一点?
hee*_*ayl 11
使用较新版本的 GNU grep(有-z选项),您可以使用这个 liner:
find . -type f -exec grep -lz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' {} +
Run Code Online (Sandbox Code Playgroud)
考虑到空格只能出现在单词之间。
如果您只想从当前目录开始递归搜索所有文件,则不需要find,您可以使用grep -r(recursive)。find可用于选择要搜索的文件,例如选择要排除的目录中的文件。所以,简单地说:
grep -rlz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' .
Run Code Online (Sandbox Code Playgroud)
这里的主要技巧是-z,它将处理以ASCII NUL而不是换行符结尾的输入流的每一行,因此我们可以使用常规方法匹配换行符。
[[:space:]] 字符类模式表示任何空白字符,包括空格、制表符、CR、LF 等。因此,我们可以使用它来匹配单词之间的所有空白字符。
grep -l将仅打印具有任何所需模式的文件名。如果您还想打印匹配项,请使用-H代替-l。
另一方面,如果空格可以出现在任何地方而不是单词,这将失去它的美观:
grep -rlz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' .
Run Code Online (Sandbox Code Playgroud)
随着-P(PCRE)选项,您可以替换[[:space:]]使用\s(这看起来更漂亮):
grep -rlz
't[[:space:]]*h[[:space:]]*i[[:space:]]*s[[:space:]]*i[[:space:]]*\
s[[:space:]]*s[[:space:]]*o[[:space:]]*m[[:space:]]*e[[:space:]]*\
t[[:space:]]*e[[:space:]]*x[[:space:]]*t' .
Run Code Online (Sandbox Code Playgroud)
使用@steeldriver 的建议sed为我们生成模式将是最好的选择:
grep -rlzP "$(sed 's/./\\s*&/2g' <<< "thisissometext")" .
Run Code Online (Sandbox Code Playgroud)
您可以删除所有空格并 grep 它:
tr -d '[[:space:]]' < foo | grep thisissometext
Run Code Online (Sandbox Code Playgroud)
扩展:
find . -type f -exec bash -c 'for i; do tr -d "[[:space:]]" < "$i" | grep -q thisissometext && printf "%s\n" "$i"; done' _ {} +
Run Code Online (Sandbox Code Playgroud)
该bash命令,扩展:
tr -d '[[:space:]]' < foo | grep thisissometext
Run Code Online (Sandbox Code Playgroud)
这会遍历所有参数并使用上述测试。