5

我仍然是 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不合适,还有什么我可以使用的吗?

4

3 回答 3

6

假设您<script>在不同的行上有标签,例如:

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

以下应该有效:

sed '/<script/,/<\/script>/d' inputfile
于 2013-07-16T08:33:31.947 回答
1

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

awk '/<script.*>/   { in=1; next }
     /<\/script.*>/ { if (in) in=0; next }
    { if (!in) print; } ' $1
于 2013-07-16T08:29:56.060 回答
0

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

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

人们会很想使用tr :

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

然而,“目前tr完全支持单字节字符”,并且为了安全起见,您可能希望使用一些不太可能的字符,例如ˇ,这tr无济于事。

sed幸运的是,同样的事情可以通过使用分支来实现。

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

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

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

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

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

  • s/\n/ˇ/gˇ 用;替换所有换行符
  • s~<script>.*</script>~~g删除需要删除的内容(请注意,它需要一些保护以供实际使用:因为它会删除第一个<script>和最后一个之间的所有内容</script> ;另外,请注意我使用~而不是/避免转义斜杠</script> :我本来可以使用几乎任何单字节字符,除了少数保留字符,如\) ;
  • s/ˇ/\n/g读取换行符。
于 2017-03-24T11:37:16.567 回答