【问题标题】:Sed regex multiline matching based on start, end and content基于开始、结束和内容的 Sed 正则表达式多行匹配
【发布时间】:2013-12-27 17:38:12
【问题描述】:

我确定该示例已经存在,但找不到它。

在数千个静态 HTML 文件中,我有如下代码块,我需要用独特的内容替换不同的 AdSense 代码块:

<div id="left">

    <div style="margin-top:1px;">
    <script type="text/javascript"><!--
    google_ad_client = "pub-123456132654";
    google_ad_slot = "9844984";
    google_ad_width = 468;
    google_ad_height = 15;
    //-->
    </script>
    <script type="text/javascript"
    src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
    </script>
    </div>
</div>

<div id="content">
<div id="googlesquare">
<script type="text/javascript"><!--
google_ad_client = "pub-123456132654";
google_ad_slot = "68468464";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>  

我找到了一些匹配 sed 使用的开始和结束的模式,但缺少内部内容匹配。

如果在另一个 CLI 工具中更好地完成,我不依赖 sed,但首选尽可能通用的 Unix 工具。

更新

这是我希望能够用一种模式捕捉的内容,而无需抓住其他模式:

【问题讨论】:

  • SO 上的每个用户都会来到这里,向您介绍正则表达式和 HTML。我会在几秒钟内发布正则表达式。 :P
  • 该示例的预期输出是什么?
  • 是的,如果我在一个精通 DOM 的域中,那么就不需要正则表达式,但在 bash 进程中需要,理想情况下,我希望能够快速完成这些事情(如果效率不高)当它们出现时。
  • @poiu2000,更新原帖

标签: html regex sed


【解决方案1】:

正则表达式

&lt;script[^&gt;]*&gt;(.*?)&lt;/script&gt;

注意事项

  • 标签之间的任何内容都存储在第一个捕获组中。
  • 不能正确匹配嵌套在自身内部的标签。

【讨论】:

  • 您能否告诉我如何针对某个已编码的容器值进行调整,即google_ad_slot = "9844984";
  • 您需要在当前匹配所有内容的第一个捕获组中指定其他正则表达式:(.*?) 例如:&lt;script[^&gt;]*&gt;(.*?(?:google_ad_slot[ ="]{4}(\d+)";).*?)&lt;/script&gt;。然后,您将使用第二个捕获组...在这种情况下,它匹配 9844984
  • 你需要匹配整个标签,匹配那些硬编码的容器值不是更容易吗?
  • 我需要匹配整个标签并将它们替换为#ADBLOCK_UNIQUE_1234# 之类的东西。我想用一个正则表达式捕获的目标块在这里:i.imgur.com/Duif8ax.png
  • 你能举一个你想要创建的完整输出的例子吗?
【解决方案2】:
sed -n '
\|<script type="text/javascript">|,\|</script>| {
    H
    \|</script>| {
       s/.*//
       x
       s/google_ad_client = "pub-123456132654";/&/
       t catch
       b nocatch

: catch
# catch code here
    s/pub-123456132654/nopub-9876543210/
    p
# end of catch block
       b
       }
  }

\|<script type="text/javascript">|,\|</script>| !{
: nocatch
# no catch code here
   p
# end of no catch block
   }
' YourFile

捕获该部分并允许您对其进行操作(此时所有部分都在工作缓冲区中,因此行 a 由 \n 分隔)。出于示例的目的,我只是将pub-123456132654 更改为nopub-9876543210,并且没有对文件进行其他操作。

找到一个部分时会添加一个新行。如果强制,可以删除它

一些解释

\|in \||` 用于将默认分隔符 (/) 更改为另一个 (|) 在这种情况下更有趣,因为 /*s

\|&lt;/script&gt;| {\|&lt;script type="text/javascript"&gt;|,\|&lt;/script&gt;| { 块用于出现在块的最后一行,如 $ 出现在文件的最后一行。

在这个子块中,交换工作和保持缓冲区(目标是进入工作缓冲区并为下一次迭代提供一个空的保持缓冲区)

bt 的 sed 工作流程有点奇怪,因为 t(如 if goto)仅在 as// 发生之后才起作用(缺少 else 或 not)

【讨论】:

  • 哦,sed 真棒!这解决了手头的问题,并为我提供了另一个有用的文本处理工具,谢谢!
  • 如果可能,您能否添加更多内联 cmets 来解释发生了什么?即,为什么` before the pipe delimiter each time? In the man pages, it does not seem to be necessary. Also, the line \|| {`,为什么在已经将目标代码块修改到缓冲区之后,它再次匹配结束脚本标记? s,x,s,t,b 块看起来清除缓冲区,然后存储匹配项。仍然喜欢 sed,但有点摸不着头脑:)
  • 我调整了答案,包括评论
  • 高度赞赏!感谢您抽出宝贵时间
猜你喜欢
  • 1970-01-01
  • 2015-07-06
  • 1970-01-01
  • 1970-01-01
  • 2022-07-05
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
  • 2020-04-03
相关资源
最近更新 更多