问题在于:我有~35k个文件,可能包含或不包含300行中包含正则表达式的列表中的一个或多个字符串
如果我grep -rnwl 'C:\out\' --include=*.txt -E --file='comp.log'
我看到有几千个包含匹配项的文件。
现在我如何获取sed删除这些包含以前使用的comp.log中的字符串的文件中的每一行?
edit:comp.log在每一行中都包含一个简单的正则表达式,但大多数情况下每个要匹配的字符串都是唯一的
这是一个如何构建的例子:
server[0-9]\/files\/bobba fett.stw
[a-z]+ mochaccino
[2-9] CheeseCakes
...
等。除了愚蠢的例子,它表明每一行都是独一无二的,除了一些变化,所以它不应该影响我真正想要的东西:看看这些行中的任何一行是否与正在处理的文件中的行匹配。它没有什么不同于&pattern / replacement /'除了我想使用文件中的模式而不是内联。
好的,这是一个更新(如果我几天之后没有回答问题,那么S.O.会住院病人) 在摆弄@ Kenavoz / @Fischer方法之后,我找到了一个完全不同的解决方案,但首先要做的事情。 为sed创建一个修改后的模式列表,以便完成工作。
以及@ werkritter完全放弃sed的方法。 (这个我发现最多......错误......"最不容易解决问题的方法)。
我无法在Windows / cygwin下使@Mklement的答案工作(它确实在ubuntu下工作,所以...不确定这意味着什么。数字。)
最终以一种更长期,可重复使用的形式解决问题的方法是一个名为PowerGrep的大学指出的精彩节目。它确实将所有其他选项从水中吹走。不幸的是它只是窗户并且它不是免费的。 (甚至不在这里做广告,事情并不便宜,但它确实解决了问题)。
所以考虑到@ werkiter的回复不是"正确的"回答,我不能只选择@Lars Fischer和@ Kenavoz的答案作为解决方案(它们相互补充),我正在授予@Kenavoz作为第一个的标记。
最后的想法:我希望有一个更简单,通用和免费的解决方案,但显然没有。
答案 0 :(得分:2)
你可以试试这个:
sed -f <(sed 's/^/\//g;s/$/\/d/g' comp.log) file > outputfile
comp.log
中的所有正则表达式都使用d
命令格式化为sed地址:/regex/d
。此命令删除与模式匹配的行。
此内部sed作为文件(process substitition)发送到应用于-f
的外部sed的file
选项。
仅删除匹配模式的字符串(不是所有行):
sed -f <(sed 's/^/s\//g;s/$/\/\/g/g' comp.log) file > outputfile
更新:
命令输出重定向到outputfile
。
答案 1 :(得分:2)
一些想法,但不是一个完整的解决方案,因为它需要一些采用你的脚本(未在问题中显示)。
我会将comp.log转换为包含必要删除的sed脚本:
cat comp.log | sed -r "s+(.*)+/\1/ d;+" > comp.sed`
这会让你的例子看起来像:
/server[0-9]\/files\/bobba fett.stw/ d;
/[a-z]+ mochaccino/ d;
/[2-9] CheeseCakes/ d;
然后我将comp.sed
脚本应用于grep报告的每个文件(使用-rnwl
需要一些过滤来获取文件名。):
sed -i.bak -f comp.sed $AFileReportedByGrep
如果你有gnu sed,你可以使用-i
inplace replacement创建.bak备份,否则使用管道到临时文件
答案 2 :(得分:0)
Kenavoz's answer和Lars Fischer's answer都使用相同的巧妙方法:
将输入正则表达式列表转换为sed
匹配和删除命令列表,通过sed
作为脚本传递给-f
。
使用单个命令来补充这些答案,假设您有 GNU sed
并且您的shell是bash
,ksh
或者zsh
(支持<(...)
):
find 'c:/out' -name '*.txt' -exec sed -i -r -f <(sed 's#.*#/\\<&\\>/d#' comp.log) {} +
find 'c:/out' -name '*.txt'
匹配dir子树中的所有*.txt
个文件。 c:/out
-exec ... +
传递的匹配文件数量与指定命令的单个命令行相同,通常只会导致单个调用。 sed -i
更新输入文件就地(从概念上讲 - 有警告);附加后缀(例如-i.bak
)以保存带有该后缀的原始文件的备份。
sed -r
激活对扩展正则表达式的支持,这是输入正则表达式。
sed -f
从指定的文件名中读取要执行的脚本,在这种情况下,如Kenavoz's answer中所述,使用进程替换(<(...)
)来封闭sed
命令的输出就像一个[瞬态]文件。
s///
sed
命令 - 使用替代定界符#
来促进 literal /
的使用 - 包含来自{{1}的每一行在comp.log
中生成所需的删除命令; /\<...\>/d
中输入正则表达式的封闭可确保匹配为单词,如\<...\>
所示。
这是需要 GNU grep -w
的主要原因,因为POSIX ERE(扩展正则表达式)和BSD / OSX sed
都不支持sed
和{{1 }}。
\<
,将\>
替换为sed
,-r
/ {{1 } -E
/ \<