我需要提取一堆html文件(大约500K)中的文本要复制的文本看起来像<div class='cls '>text to be copied including some<span>and <p></p></span>and more text</div>
我决定(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)
我读过有关如何使用 grep 执行此操作的其他问题,我认为该命令是
grep -r "/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" *.html > output.txt
但这不起作用。我究竟做错了什么?
也尝试过pcregrep -r -regexp="/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" --file-list=fl.txt > output.txt
- 它什么也没做pcregrep -r -regexp="/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" > output.txt
- 什么也没做
编辑1:尝试以下格式的建议:
grep -f -r "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" *.html >> touch output.txt
grep: -r: No such file or directory
grep -f -r "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" *.html >> output.txt
grep: -r: No such file or directory
grep -f -r "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" *.html >> output.txt
grep: -r: No such file or directory
grep -f "/(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/" file111.html >> touch output.txt
grep: /(?:\<div\sclass\=\'desc\s\'\>)(.*)(?=\<\/div\>)/: No such file or directory
和其他一些排列,仍然没有
答案1
不知道为什么你添加了所有这些花哨的广告口哨。这个简单的正则表达式对我有用:
grep "<div\sclass='cls\s'>.*<\/div>" file
<div class='cls '>text to be copied including some<span>and <p></p></span>and more text</div>
答案2
你有六个问题:
- 您
/
在正则表达式的开头和结尾处包含了内容。您输入、和其他程序来进行搜索,但不需要它。事实上,只会在模式中包含文字字符。/regex/
sed
vi
grep
grep
/
- 要在 (plain) 中使用 PCRE
grep
,您必须使用-P
. - 不存在这样的事情
-regexp
;它一定要是--regexp
。或者省略 并将—regexp=
正则表达式作为朴素的参数给出,就像在 中所做的那样grep
。
一旦我修复了上述错误,两个命令 (grep -P
和pcregrep
) 都可以工作 - 但它们打印了包含模式的整行,包括 . 之前<div …>
或之后的任何文本</div>
。
- 要仅打印与模式匹配的文本,您必须指定
-o
。
即使我解决了这个问题,我还是<div …>
在输出中得到了(但不是之前的文本<div …>
,或者</div>
之后的任何内容)。所以,
您的后视组出现问题 - 它被包含在比赛中。
不幸的是,我对 PCRE 的了解不够,无法确切地知道问题是什么或如何解决它。幸运的是,我了解得足够多,
pcregrep
知道解决方法。如果您的正则表达式中有多个捕获组,pcregrep
您可以选择要写入输出的捕获组。因此,我们可以pcregrep
通过将后视转换为捕获组,然后忽略它来使其工作:pcregrep -o2-r "(\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)"
但即使这样也比需要的更复杂。第一个 (
<div …>
) 组不必是捕获组;即,它根本不必是一个组。同样,最后一个组(</div>
前瞻组)根本不必是一个组。唯一需要成为一个组的是您想要捕获的部分 -<div …>
和之间的部分</div>
:pcregrep-o1-r "\<div\sclass\=\'cls\s\'\>(.*)\<\/div\>"
请注意,我更改
-o2
为-o1
因为现在只有一组。顺便说一句,作为鲁迪克发现(但没有提及),这些反斜杠几乎都不是必要的。 AFAICT,您唯一需要的是
\s
字符串中的那些;所以我们可以将上面的内容简化为:pcregrep -o1 -r "<div\sclass='cls\s'>(.*)</div>"
现在我们已经消除了正则表达式的所有 PCRE 部分(前向和后向),您可能认为我们可以将此正则表达式与普通
grep
.不幸的是,我们不能;上面的命令取决于选项,而选项则没有。-oN
grep
但是,我们可以将它与
sed
!sed -n -r "s|.*<div\sclass='cls\s'>(.*)</div>.*|\1|p"
与该
pcregrep
命令一样,这会搜索整个正则表达式(包括 之前<div …>
或之后的内容</div>
,因为我.*
在开头和结尾添加了内容)并将其替换为 #1 捕获组(唯一的一个)。末尾的p
导致它打印匹配的行;该-n
选项导致它不打印不匹配的行。上面用作
|
正则表达式分隔符,因为正则表达式包含/
.如果您想用作/
分隔符,那么您必须转义文本/
(在 中</div>
):sed -n -r "s/.*<div\sclass='cls\s'>(.*)<\/分区>.*/\1/”
不幸的是,
sed
没有递归搜索功能。选项类似于;-r
它指定扩展正则表达式 (ERE) 的使用。如果没有它,我们需要使用and作为捕获组:sed
-E
grep
\(
\)
sed -n "s/.*<div\sclass='cls\s'>\(.*\)<\/div>.*/\1/p"
sed
当然,您可以通过运行来进行递归搜索find
。PS 如果一行中有多个
<div …>
…对,这些命令将仅打印第一个。</div>
sed
您的递归(目录树)搜索错误。
grep -r正则表达式*.html
(
pcregrep
同样)查看每个.html
文件,然后查看每一个文件在任何 名称结尾为的目录.html
。因此,如果(不太可能?)您有一个名为 的子目录foo.html
,那么上面的命令将搜索每一个该目录中的文件(即使它被称为Makefile
orREADME.txt
)。如果(我认为更有可能)您有名称类似于page42
和 的子目录index
,则不会搜索它们。你想做的是:
grep -r --include='*.html'正则表达式。
它对从以下位置开始的所有目录进行递归搜索
.
(当前目录),仅查看名称匹配的文件*.html
。
答案3
grep -r "/(?:\<div\sclass\=\'cls\s\'\>)(.*)(?=\<\/div\>)/" *.html > output.txt
正在递归工作但不解释正则表达式。尝试改用 fgrep 或 grep -f -r。另外,您可能想touch output.txt
使用 >> 而不是 >。