在正则表达式中找到模式的第一次出现

时间:2013-07-07 16:01:21

标签: html regex notepad++ expression

我知道在重复提问之前已经有一百万次这样的问题,但这让我感到疯狂。我现在已经做了很多年了,似乎没有任何地方。

我有一些html代码,其中包含向右或向左浮动的图像。我需要做的是找到浮动的所有图像,移除浮动然后将它们包裹在一个div中,该div现在以与图像相同的方式浮动。

e.g。 从

<img src="images/imagepath1.jpg" border="0" alt="image 1" width="200" height="206" style="float: right;" />

<div class="imgContainer" style="float: right;"><img src="images/imagepath1.jpg" border="0" alt="image 1" width="200" height="206" /></div>

我在Notepad ++中使用此代码 查找

<img src="(.+)" border="([0-9]{1})" alt="(.*?)" width="([0-9]{2,3})" height="([0-9]{3})" style="float: (right|left);" />

替换为

<div class="imgContainer" style="float: \6;"><img src="\1" border="\2" alt="\3" width="\4" height="\5" /></div>

问题是在包含<p>标签和多个图像的代码块中,我从头到尾突出显示整个代码块。

E.g。

<img src="images/imagepath1.gif" border="0" alt="image 1" width="207" height="119" style="float: right;" /><p>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum</p><p>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum </p><p>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum</p> <img src="images/imagepath2.jpg" border="0" alt="image2" width="96" height="141" style="float: left;" /><p>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum </p><p>Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum </p><img src="images/imagepath3.gif" border="0" alt="image 3" width="72" height="108" style="float: right;" />

在notepad ++中,这匹配整个块。你能提出任何让我疯狂的建议吗?

亚当

2 个答案:

答案 0 :(得分:1)

转发

确保您使用的是最新版本的notepad ++,其中在notepad ++ v5中使用正则表达式时已知问题,之前已在v6中更正过。

基本

虽然有很多边缘情况,正则表达式难以处理HTML,例如:

  • 属性可以在标记
  • 中以任何顺序出现
  • 属性值可以看起来像<img onmouseover=' src="TheseAreNotTheDroidsYouAreLookingFor.png" ; funImageSwap(src); ' src="DecoyDroids.png">
  • 等实际属性
  • 属性值可以使用单引号或无引号

在您的表达中,请考虑将.+更改为[^"]+。这将阻止正则表达式引擎离开引用区域或标记并进入下一个可能的匹配

<img src="([^"]+)" border="([0-9]{1})" alt="([^"]*?)" width="([0-9]{2,3})" height="([0-9]{3})" style="float: (right|left);" />

但这并不能处理其他边缘情况。

复合

要绕过这些边缘情况,您可以使用此怪物表达式。我有多行,并在这里评论,以显示正在发生的事情,以帮助使其更容易理解。但是在记事本中,您需要删除评论和所有新行。

正则表达式

<img(?=\s|>)
(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\ssrc=('[^']*'|"[^"]*"|[^'"][^\s>]*)) # find src, capture value including quotes if they exist
(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sborder=('[^']*'|"[^"]*"|[^'"][^\s>]*))  # find border, capture value including quotes if they exist
(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\salt=('[^']*'|"[^"]*"|[^'"][^\s>]*)) # find alt, capture value including quotes if they exist
(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\swidth=('[^']*'|"[^"]*"|[^'"][^\s>]*))   # find width, capture value including quotes if they exist
(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sheight=('[^']*'|"[^"]*"|[^'"][^\s>]*))  # find height, capture value including quotes if they exist
(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sstyle="[^"]*(float:\s*(?:right|left)))  # find style, capture value including quotes if they exist
[^>]*>                      # actually capture the string

替换为

<div class="imgContainer" style="$6;"><img src=$1 border=$2 alt=$3 width=$4 height=$5 /></div>

这是插入我的记事本示例中的单行表达式。我使用的是notepad ++ v6.3.3

<img(?=\s|>)(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\ssrc=('[^']*'|"[^"]*"|[^'"][^\s>]*))(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sborder=('[^']*'|"[^"]*"|[^'"][^\s>]*))(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\salt=('[^']*'|"[^"]*"|[^'"][^\s>]*))(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\swidth=('[^']*'|"[^"]*"|[^'"][^\s>]*))(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sheight=('[^']*'|"[^"]*"|[^'"][^\s>]*))(?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sstyle="[^"]*(float:\s*(?:right|left)))[^>]*>

enter image description here

扩展

  • <img匹配图片代码
  • (?=\s|>)向前看以确保图片标记名称后跟空格或近角括号
  • (?=向前看,这个特殊的人找到了src属性,但其他所有人的想法都是一样的。前瞻允许属性以标记内的任何顺序出现,因为在满足前瞻后,正则表达式引擎返回到前瞻开始的位置并继续表达式的其余部分。
    • (?:非捕获组将正则表达式游标移动到字符串中,跳过所有引用的属性值。这是绕过可能被误认为理想属性名称的属性值的魔力。
    • [^>=]匹配所有不是括号或等号的字符
    • |
    • ='[^']*'匹配等号后跟单引号,所有文字都在单引号内并关闭单引号
    • |
    • ="[^"]*"匹配等号,后跟双引号,双引号内的所有文字并关闭双引号
    • |
    • =[^'"][^\s>]*一个等号后跟一个非引号字符,后跟任意数量的非空格或近角括号的字符
    • )*?关闭非捕获组,并允许它根据需要重复多次。捕获不会离开标签,所以如果不满足下一个条件,那么这个特定的标签不是我们正在寻找的标签
  • \ssrc=匹配后跟src=的空格。由于上面的非捕获组,这只能是属性名称
  • (启动捕获组,这将获取src属性的值
    • '[^']*'匹配等号后跟单引号,所有文字都在单引号内并关闭单引号
    • |
    • "[^"]*"匹配等号,后跟双引号,双引号内的所有文字并关闭双引号
    • |
    • [^'"][^\s>]*一个等号后跟一个非引号字符,后跟任意数量的非空格或近角括号的字符
    • )关闭捕获组
  • )关闭前瞻
  • 这些下一个前瞻都遵循与上述src相同的逻辑
    • (?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sborder=('[^']*'|"[^"]*"|[^'"][^\s>]*))找到边框,捕获值包括引号(如果存在)
    • (?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\salt=('[^']*'|"[^"]*"|[^'"][^\s>]*))查找alt,捕获值(包括引号,如果存在)
    • (?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\swidth=('[^']*'|"[^"]*"|[^'"][^\s>]*))找到宽度,捕获值包括引号(如果存在)
    • (?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sheight=('[^']*'|"[^"]*"|[^'"][^\s>]*))查找高度,捕获值(包括引号,如果存在)
    • (?=(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sstyle="[^"]*(float:\s*(?:right|left)))找到样式,捕获值因为实际属性值的匹配方式略有不同
  • [^>]*>匹配img标记和close括号的其余部分,这可以防止正则表达式引擎意外地找到包含的属性,该属性的值可能被误认为是另一个img标记。

答案 1 :(得分:1)

我会说你在正确的道路上只有一个角色远离正则表达式找到/替换你想出来。

这是您当前的发现:

<img src="(.+)" border="([0-9]{1})" alt="(.*?)" width="([0-9]{2,3})" height="([0-9]{3})" style="float: (right|left);" />

将其更改为:

             v

<img src="(.+?)" border="([0-9]{1})" alt="(.*?)" width="([0-9]{2,3})" height="([0-9]{3})" style="float: (right|left);" />

v显示我介绍您当前缺少的1个字符的位置。一旦你使这个.+懒惰,你应该能够得到正确的替换,而不是整个事情的单一替换。

也就是说,在这种情况下,我也建议使用[^"]代替.