【问题标题】:sed - Include newline in patternsed - 在模式中包含换行符
【发布时间】:2013-07-16 08:16:38
【问题描述】:

我仍然是 shell 脚本的菜鸟,但我正在努力。下面是一个部分工作的 shell 脚本,它应该通过匹配标签并删除它们包含的内容来从 *.htm 文档中删除所有 JS。例如。 <script src=""><script></script><script type="text/javascript">

find $1 -name "*.htm" > ./patterns
for p in $(cat ./patterns)
do
sed -e "s/<script.*[.>]//g" $p #> tmp.htm ; mv tmp.htm $p
done

这个脚本的问题是,因为 sed 逐行读取文本输入,所以这个脚本不能像预期的那样使用换行符。运行:

<script>
//Foo
</script>

将删除第一个脚本标记,但会省略我不想要的“foo”和结束标记。

有没有办法在我的正则表达式中匹配换行符?或者如果sed 不合适,还有什么我可以使用的吗?

【问题讨论】:

    标签: regex shell sed cygwin


    【解决方案1】:

    假设您在不同的行上有 &lt;script&gt; 标签,例如类似:

    foo
    bar
    <script type="text/javascript">
    some JS
    </script>
    foo
    

    以下应该有效:

    sed '/<script/,/<\/script>/d' inputfile
    

    【讨论】:

    • 经过测试。有用。我遇到的唯一问题是同一行上的字符与脚本标记一起被替换。例如foo
    【解决方案2】:

    awk 脚本将查找&lt;script*&gt; 标记,设置in 变量,然后读取下一行。当找到结束&lt;/script*&gt; 标记时,变量设置为零。如果in 变量为零,则最终打印模式输出所有行。

    awk '/<script.*>/   { in=1; next }
         /<\/script.*>/ { if (in) in=0; next }
        { if (!in) print; } ' $1
    

    【讨论】:

      【解决方案3】:

      正如您所提到的,问题在于sed 逐行处理输入。

      因此,最简单的解决方法是将输入设为单行,例如用您确信输入中不存在的字符替换换行符。

      人们会很想使用tr

      … |tr '\n' '_'|sed 's~<script>.*</script>~~g'|tr '_' '\n'
      

      但是“currently tr fully supports only single-byte characters”,为了安全起见,您可能希望使用一些不太可能的字符,例如ˇtr 对此无济于事。

      幸运的是,sedusing branching 也可以实现同样的效果。

      回到我们的 &lt;script&gt;…&lt;/script&gt; 示例,这确实有效,并且(根据上一个链接)将是跨平台的:

      … |sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ˇ/g' -e 's~<script>.*</script>~~g' -e 's/ˇ/\n/g'
      

      如果您使用 GNU sed 并且不需要跨平台兼容性,则可以采用更简洁的形式:

      … |sed ':a;N;$!ba;s/\n/ˇ/g;s~<script>.*</script>~~g;s/ˇ/\n/g'
      

      有关分支部分的详细信息,请参阅“使用分支”下的链接答案(:a;N;$!ba;)。剩下的部分很简单:

      • s/\n/ˇ/g 将所有换行符替换为 ˇ
      • s~&lt;script&gt;.*&lt;/script&gt;~~g 删除需要删除的内容(注意它需要一些保护以供实际使用:因为它会删除第一个 &lt;script&gt; 和最后一个 &lt;/script&gt; 之间的所有内容;另外,请注意我使用 ~ 而不是/ 以避免在 &lt;/script&gt; 中转义斜线:我可以使用几乎任何单字节字符,除了一些保留字符,如 \);
      • s/ˇ/\n/g 读取换行符。

      【讨论】:

      • 请注意,如果您需要执行不依赖于分支的操作​​,将sed 输出传递到新的sed 实例可能更明智(我自己遇到了一些操作工作的问题在同一实例中,其他实例不在)。
      猜你喜欢
      • 2023-02-09
      • 2013-08-22
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多