我正在尝试提取锚标记(<a>)的属性.到目前为止,我有这样的表达:
(?<name>\b\w+\b)\s*=\s*("(?<value>[^"]*)"|'(?<value>[^']*)'|(?<value>[^"'<> \s]+)\s*)+
Run Code Online (Sandbox Code Playgroud)
适用于字符串之类的
<a href="test.html" class="xyz">
Run Code Online (Sandbox Code Playgroud)
和(单引号)
<a href='test.html' class="xyz">
Run Code Online (Sandbox Code Playgroud)
但不是没有引号的字符串:
<a href=test.html class=xyz>
Run Code Online (Sandbox Code Playgroud)
如何修改我的正则表达式使其适用于没有引号的属性?或者有更好的方法吗?
谢谢!
更新: 感谢您提供的所有好评和建议.有一件事我没有提到:遗憾的是我必须修补/修改我自己编写的代码.没有时间/金钱可以自下而上重写这些东西.
Von*_*onC 86
如果你有像这样的元素
<name attribute=value attribute="value" attribute='value'>
Run Code Online (Sandbox Code Playgroud)
此正则表达式可用于连续查找每个属性名称和值
(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?
Run Code Online (Sandbox Code Playgroud)
应用于:
<a href=test.html class=xyz>
<a href="test.html" class="xyz">
<a href='test.html' class="xyz">
Run Code Online (Sandbox Code Playgroud)
它会产生:
'href' => 'test.html'
'class' => 'xyz'
Run Code Online (Sandbox Code Playgroud)
注意:这不适用于数字属性值,例如
<div id="1">不起作用.
Axe*_*man 22
虽然不通过regexp解析HTML的建议是有效的,但这里的表达式几乎与您提出的要求相同:
/
\G # start where the last match left off
(?> # begin non-backtracking expression
.*? # *anything* until...
<[Aa]\b # an anchor tag
)?? # but look ahead to see that the rest of the expression
# does not match.
\s+ # at least one space
( \p{Alpha} # Our first capture, starting with one alpha
\p{Alnum}* # followed by any number of alphanumeric characters
) # end capture #1
(?: \s* = \s* # a group starting with a '=', possibly surrounded by spaces.
(?: (['"]) # capture a single quote character
(.*?) # anything else
\2 # which ever quote character we captured before
| ( [^>\s'"]+ ) # any number of non-( '>', space, quote ) chars
) # end group
)? # attribute value was optional
/msx;
Run Code Online (Sandbox Code Playgroud)
"但是等等,"你可能会说."那么*评论呢?!?!" 好的,那么你可以用以下内容替换.非回溯部分:(它还处理CDATA部分.)
(?:[^<]|<[^!]|<![^-\[]|<!\[(?!CDATA)|<!\[CDATA\[.*?\]\]>|<!--(?:[^-]|-[^-])*-->)
Run Code Online (Sandbox Code Playgroud)
\K在属性名称前面放置,而不必担心捕获您想要跳过的所有内容.Ken*_*ric 13
Token Mantra响应:您不应该使用正则表达式调整/修改/收获/或以其他方式生成html/xml.
还有一些必须要考虑的问题,例如"和"这样的极端情况条件.你最好使用适当的DOM解析器,XML解析器,或其他许多经过试验和测试的工具来代替这项工作.发明自己的.
我不关心你使用哪一个,只要它被认可,测试,你使用一个.
my $foo = Someclass->parse( $xmlstring );
my @links = $foo->getChildrenByTagName("a");
my @srcs = map { $_->getAttribute("src") } @links;
# @srcs now contains an array of src attributes extracted from the page.
Run Code Online (Sandbox Code Playgroud)
bob*_*nce 11
只是为了与其他人一致:不要使用regexp解析HTML.
不可能创建一个表达式来为即使是正确的HTML片段选择属性,也不要介意所有可能的格式错误的变体.你的正则表达式已经非常难以理解,即使没有尝试应对无效的报价缺失; 进一步追逐真实世界HTML的恐怖,你会因为不可靠的不可靠表达而让自己疯狂.
现有的库可以读取损坏的HTML,或者将其更正为有效的XHTML,然后您可以轻松地使用XML解析器.使用它们.
Gum*_*mbo 11
您不能对多个捕获使用相同的名称.因此,您不能在具有命名捕获的表达式上使用量词.
所以要么不使用命名捕获:
(?:(\b\w+\b)\s*=\s*("[^"]*"|'[^']*'|[^"'<>\s]+)\s+)+
Run Code Online (Sandbox Code Playgroud)
或者不要在此表达式上使用量词:
(?<name>\b\w+\b)\s*=\s*(?<value>"[^"]*"|'[^']*'|[^"'<>\s]+)
Run Code Online (Sandbox Code Playgroud)
这也允许属性值,如bar=' baz='quux:
foo="bar=' baz='quux"
Run Code Online (Sandbox Code Playgroud)
那么缺点是你必须在之后删除前导和尾随引号.
简单的属性提取(见工作):
((?:(?!\s|=).)*)\s*?=\s*?["']?((?:(?<=")(?:(?<=\\)"|[^"])*|(?<=')(?:(?<=\\)'|[^'])*)|(?:(?!"|')(?:(?!\/>|>|\s).)+))
Run Code Online (Sandbox Code Playgroud)
或者使用标记打开/关闭验证,标记名称检索和注释转义.此表达式预见到未加引号/引号,单引号或双引号,属性内的转义引号,等号周围的空格,不同的属性数,仅检查标记内的属性,以及管理属性值中的不同引号.(见工作):
(?:\<\!\-\-(?:(?!\-\-\>)\r\n?|\n|.)*?-\-\>)|(?:<(\S+)\s+(?=.*>)|(?<=[=\s])\G)(?:((?:(?!\s|=).)*)\s*?=\s*?[\"']?((?:(?<=\")(?:(?<=\\)\"|[^\"])*|(?<=')(?:(?<=\\)'|[^'])*)|(?:(?!\"|')(?:(?!\/>|>|\s).)+))[\"']?\s*)
Run Code Online (Sandbox Code Playgroud)
(使用"gisx"标志更好地工作.)
由于Javascript正则表达式不支持后视,因此它不支持我建议的先前表达式的大多数功能.但是如果它可能符合某人的需要,你可以尝试这个版本.(见工作).
(\S+)=[\'"]?((?:(?!\/>|>|"|\'|\s).)+)
Run Code Online (Sandbox Code Playgroud)
这是我提取HTML Tag中的属性的最佳RegEx:
#在引号内修剪匹配项(单引号或双引号)
(\S+)\s*=\s*([']|["])\s*([\W\w]*?)\s*\2
Run Code Online (Sandbox Code Playgroud)
#不带修剪
(\S+)\s*=\s*([']|["])([\W\w]*?)\2
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
<div title="You're">结果是第1组:标题,第2组:“,第3组:您是。这是在线RegEx示例:https : //regex101.com/r/aVz4uG/13
我通常使用此RegEx提取HTML标签:
如果您不使用,等标签类型<div,则建议您这样做<span。
<[^/]+?(?:\".*?\"|'.*?'|.*?)*?>
Run Code Online (Sandbox Code Playgroud)
例如:
<div title="a>b=c<d" data-type='a>b=c<d'>Hello</div>
<span style="color: >=<red">Nothing</span>
# Returns
# <div title="a>b=c<d" data-type='a>b=c<d'>
# <span style="color: >=<red">
Run Code Online (Sandbox Code Playgroud)
这是在线RegEx示例:https : //regex101.com/r/aVz4uG/15
此RegEx中的错误是:
<div[^/]+?(?:\".*?\"|'.*?'|.*?)*?>
Run Code Online (Sandbox Code Playgroud)
在这个标签中:
<article title="a>b=c<d" data-type='a>b=c<div '>Hello</article>
Run Code Online (Sandbox Code Playgroud)
返回,<div '>但不应返回任何匹配项:
Match: <div '>
Run Code Online (Sandbox Code Playgroud)
要“解决”此删除[^/]+?模式:
<div(?:\".*?\"|'.*?'|.*?)*?>
Run Code Online (Sandbox Code Playgroud)
答案#317081很好,但与这些情况不正确匹配:
<div id="a"> # It returns "a instead of a
<div style=""> # It doesn't match instead of return only an empty property
<div title = "c"> # It not recognize the space between the equal (=)
Run Code Online (Sandbox Code Playgroud)
这是改进:
(\S+)\s*=\s*["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))?[^"']*)["']?
Run Code Online (Sandbox Code Playgroud)
与
(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?
Run Code Online (Sandbox Code Playgroud)
避免等号之间的空格:(\ S +)\ s * = \ s *((?
更改最后的+和。用于:| [>“']))?[^”'] *)[“']?
这是在线RegEx示例:https : //regex101.com/r/aVz4uG/8
HTML 中的标签和属性具有以下形式
<tag
attrnovalue
attrnoquote=bli
attrdoublequote="blah 'blah'"
attrsinglequote='bloob "bloob"' >
Run Code Online (Sandbox Code Playgroud)
要匹配属性,您需要一个attr可查找四种形式之一的正则表达式。然后,您需要确保仅报告 HTML 标记内的匹配项。假设您有正确的正则表达式,总的正则表达式将是:
attr(?=(attr)*\s*/?\s*>)
Run Code Online (Sandbox Code Playgroud)
前瞻确保只有其他属性和结束标记位于该属性之后。我使用以下正则表达式attr:
\s+(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^><"'\s]+)))?
Run Code Online (Sandbox Code Playgroud)
不重要的组被设为非捕获组。第一个匹配组$1为您提供属性的名称,值为 $2或$3之一$4。我用来$2$3$4提取值。最终的正则表达式是
\s+(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^><"'\s]+)))?(?=(?:\s+\w+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^><"'\s]+))?)*\s*/?\s*>)
Run Code Online (Sandbox Code Playgroud)
注意:我删除了前瞻中所有不必要的组,并使所有剩余的组不捕获。
| 归档时间: |
|
| 查看次数: |
92737 次 |
| 最近记录: |