我正在尝试使用正则表达式从文本文件中删除某些编码块。到目前为止,我的大多数正则表达式行都已删除代码。但是,我有两个问题:
1)每当我删除一段文本时,文本应该用空格代替,而不是简单地删除。 我的正则表达式代码的一个例子是:
$file =~ s/<ul(.*)>//gi;
使用基本格式<ul...>
删除所有行,这是我想要它做的。但是,如前所述,它用空格替换标签和所有包含的数据,我想知道如何停止这种特殊的替换。
2)某些应该有效的正则表达式代码似乎没有。例如,我想删除
<script type="text/javascript">
function getCookies() { return ""; }
</script>
我尝试使用各种正则表达式代码,但似乎没有删除这些行。例如:
$file =~ s/<script type(.*)<\/script>//gi;
分别删除<script type...>
和</script>
标记,但保留
function getCookies() { return ""; }
...完好。我不确定为什么会发生这种情况,我非常想纠正这个问题。这怎么可能?对这两个问题中的任何一个问题的任何帮助都会非常有帮助!
编辑:对不起,我正在使用Perl! 另外:我刚尝试使用
$file =~ /<script type(.*)<\/script>/sgi
...以及/ msgi
,但不幸的是都没有奏效。 <script type>
和</script>
标记都已删除,但出于某种原因
function getCookies() { return ""; }
...部分留了下来。这是我的整个代码,包括所有正则表达式:
use strict;
use warnings;
my $firstarg;
if ($ARGV[0]){
$firstarg = $ARGV[0];
}
open (DATA, $ARGV[1]);
my $file = do {local $/; <DATA>};
$file =~ s/<\!DOCTYPE(.*)>//gi;
$file =~ s/<html>//gi;
$file =~ s/<\/html>//gi;
$file =~ s/<title>//gi;
$file =~ s/<\/title>//gi;
$file =~ s/<head>//gi;
$file =~ s/<\/head>//gi;
$file =~ s/<link(.*)>//gi;
$file =~ s/<\link>//gi;
$file =~ s/CDM(.*)\;//gi;
$file =~ s/<\!(.*)->//gi;
$file =~ s/<body(.*)>//gi;
$file =~ s/<\/body>//gi;
$file =~ s/<div(.*)>//gi;
$file =~ s/<\/div>//gi;
$file =~ s/function(.*)>//gi;
$file =~ s/<noscript>//gi;
$file =~ s/<\/noscript>//gi;
$file =~ s/<a(.*)>//gi;
$file =~ s/<\/a>//gi;
$file =~ s/<ul(.*)>//gi;
$file =~ s/<\/ul>//gi;
$file =~ s/<li(.*)>//gi;
$file =~ s/<\/li>//gi;
$file =~ s/<form(.*)>//gi;
$file =~ s/<\/form>//gi;
$file =~ s/<iframe(.*)>//gi;
$file =~ s/<\/iframe>//gi;
$file =~ s/<select(.*)>//gi;
$file =~ s/<\/select>//gi;
$file =~ s/<textarea(.*)>//gi;
$file =~ s/<\/textarea>//gi;
$file =~ s/<b>//gi;
$file =~ s/<\/b>//gi;
$file =~ s/<H1>//gi;
$file =~ s/<H2>//gi;
$file =~ s/<H3>//gi;
$file =~ s/<H4>//gi;
$file =~ s/<H5>//gi;
$file =~ s/<H6>//gi;
$file =~ s/<\/H1>//gi;
$file =~ s/<\/H2>//gi;
$file =~ s/<\/H3>//gi;
$file =~ s/<\/H4>//gi;
$file =~ s/<\/H5>//gi;
$file =~ s/<\/H6>//gi;
$file =~ s/<option(.*)>//gi;
$file =~ s/<\/option>//gi;
$file =~ s/<p>//gi;
$file =~ s/<\/p>//gi;
$file =~ s/<span(.*)>//gi;
$file =~ s/<\/span>//gi;
$file =~ s/<!doctype(.*)>//gi;
$file =~ s/<base(.*)>//gi;
$file =~ s/<br>//gi;
$file =~ s/<hr>//gi;
$file =~ s/<img(.*)>//gi;
$file =~ s/<input(.*)>//gi;
$file =~ s/<link(.*)>//gi;
$file =~ s/<meta(.*)>//gi;
$file =~ s/<script type(.*)<\/script>//gi;
print $file;
好的,现在我删除了导致一个问题的<script>
正则表达式,另一个已创建 - 使用:
$file =~ s/<script type(.*)<\/script>//gi;
删除<script ...>
的第一个实例之间的所有内容,但不删除标记本身,而不是整个标记的重复。使用:
$file =~ s/<script type(.*)<\/script>//mgi;
导致完全相同的事情。使用:
$file =~ s/<script type(.*)<\/script>//sgi;
导致打印多个新行字符,但没有其他文本,/msgi
相同。
呃,问题永远不会结束...... :(
新编辑:我想就发布使用正则表达式解析HTML的问题而道歉。我意识到编程界对这种做法存在相当大的反对(或者在实践中尝试,因为这似乎经常失败)。但是,我很遗憾地被迫使用正则表达式来解析选择的 HTML,这些HTML可以删除大多数(如果不是全部)HTML标记。我不被允许使用模块,尽管这是最明显和最简单的答案。
答案 0 :(得分:1)
我不确定您使用的是哪种编程语言,但假设您使用的是perl,请尝试将s
修饰符放在正则表达式的末尾:
$file =~ /<script type(.*)<\/script>/sgi
/s
修饰符使.
匹配任何字符,包括换行符(通常不包括换行符)
编辑:我道歉,我不擅长Perl,但我做了一些环顾四周,我终于意识到前面的s/
是替换。在这种情况下,你的正则表达式应该是:
$file =~ s/<script type(.*)<\/script>/sgi
删除所有内容,包括脚本标记。但是,如果您只想要标记之间的内容:
$file =~ s/(<script type="[^"]*"\s*>).*(<\/script>)/$1$2/sgi;
注意斜杠之间的$1$2
。此文本是替换文本。在这种情况下,我们使用捕获组的文本代替原始文本。在您的问题中,您连续使用两个斜杠(s/<ul(.*)>//gi
),这意味着您将整个匹配替换为空字符串。在我看来,你实际上是想用s/<ul(.*)>/ /gi
之类的空格(ASCII 20)替换所有内容。
自上次编辑以来 - 您需要为脚本使用一个正则表达式,因为您不需要内容:
$file =~ s/(<script type="[^"]*"\s*>).*(<\/script>)/ /sgi;
和所有其他标签的另一个通用正则表达式:
$file =~ s/<\/?\s*[^>]+>//sgi
我在这里假设您不希望仅限于上面显示的标签,您只想杀死所有HTML。有一个名为html2text的* nix实用程序可以执行此操作。您可能希望使用它。
答案 1 :(得分:1)
回复你的上一条评论:
perl -e'$file="<script etc>\nfoo\n</script>bar"; $file =~ s/<script.*script>//gis; print $file'
这似乎按照别人的建议做了你想做的事。但是,我不知道这与你正在尝试的有什么不同。
...
你可以加上这个:
use Data::Dumper;
$Data::Dumper::Useqq=1;
print Dumper($file);
在正则表达式之前给我们结果?
.....
宾果:
$ file = ~list的第5行和第6行已将它们过滤掉:
$file =~ s/<\!DOCTYPE(.*)>//gi;
$file =~ s/<html>//gi;
$file =~ s/<\/html>//gi;
$file =~ s/<title>//gi;
$file =~ s/<\/title>//gi;
## Here they come:
$file =~ s/<script(.*)>//gi;
$file =~ s/<\/script>//gi;
$file =~ s/<head>//gi;
答案 2 :(得分:1)
如果您不允许使用除Perl正则表达式之外的任何内容,那么您可以调整the code to strip HTML tags from a text:
#!/usr/bin/perl -w
use strict;
use warnings;
$_ = do { local $/; <DATA> };
# see http://www.perlmonks.org/?node_id=161281
# ALGORITHM:
# find < ,
# comment <!-- ... -->,
# or comment <? ... ?> ,
# or one of the start tags which require correspond
# end tag plus all to end tag
# or if \s or ="
# then skip to next "
# else [^>]
# >
s{
< # open tag
(?: # open group (A)
(!--) | # comment (1) or
(\?) | # another comment (2) or
(?i: # open group (B) for /i
( # one of start tags
SCRIPT | # for which
APPLET | # must be skipped
OBJECT | # all content
STYLE # to correspond
) # end tag (3)
) | # close group (B), or
([!/A-Za-z]) # one of these chars, remember in (4)
) # close group (A)
(?(4) # if previous case is (4)
(?: # open group (C)
(?! # and next is not : (D)
[\s=] # \s or "="
["`'] # with open quotes
) # close (D)
[^>] | # and not close tag or
[\s=] # \s or "=" with
`[^`]*` | # something in quotes ` or
[\s=] # \s or "=" with
'[^']*' | # something in quotes ' or
[\s=] # \s or "=" with
"[^"]*" # something in quotes "
)* # repeat (C) 0 or more times
| # else (if previous case is not (4))
.*? # minimum of any chars
) # end if previous char is (4)
(?(1) # if comment (1)
(?<=--) # wait for "--"
) # end if comment (1)
(?(2) # if another comment (2)
(?<=\?) # wait for "?"
) # end if another comment (2)
(?(3) # if one of tags-containers (3)
</ # wait for end
(?i:\3) # of this tag
(?:\s[^>]*)? # skip junk to ">"
) # end if (3)
> # tag closed
}{}gsx; # STRIP THIS TAG
print;
__END__
<html><title>remove script, ul</title>
<script type="text/javascript">
function getCookies() { return ""; }
</script>
<body>
<ul><li>1
<li>2
<p>paragraph
remove script, ul
1
2
paragraph
注意:此正则表达式不适用于嵌套标记容器,例如:
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Nested <object> example</title>
<body>
<object data="uri:here">fallback content for uri:here
<object data="uri:another">uri:another fallback
</object>!!!this text should be striped too!!!
</object>
Nested <object> example
!!!this text should be striped too!!!
Don't parse html with regexs.使用html解析器或在其上构建的工具,例如HTML::Parser
:
#!/usr/bin/perl -w
use strict;
use warnings;
use HTML::Parser ();
HTML::Parser->new(
ignore_elements => ["script"],
ignore_tags => ["ul"],
default_h => [ sub { print shift }, 'text'],
)->parse_file(\*DATA) or die "error: $!\n";
__END__
<html><title>remove script, ul</title>
<script type="text/javascript">
function getCookies() { return ""; }
</script>
<body>
<ul><li>1
<li>2
<p>paragraph
<html><title>remove script, ul</title>
<body>
<li>1
<li>2
<p>paragraph
答案 3 :(得分:0)
你必须要比这更谨慎。请参阅this answer中的两种方法。
答案 4 :(得分:0)
此:
$file =~ s/<div(.*)>//gi;
不会做你期望的。 '*'运算符是贪心的。如果你有一行:
hello<div id="foo"><b>bar!</b>baz
它将尽可能多地替代,只留下:
hellobaz
你想:
$file =~ s/<div[^>]*>//gi;
或
$file =~ s/<div.*?>//gi;