我仍然是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
不合适,我还可以使用其他任何东西吗?
答案 0 :(得分:5)
假设您在不同的行上有<script>
个标记,例如类似的东西:
foo
bar
<script type="text/javascript">
some JS
</script>
foo
以下内容应该有效:
sed '/<script/,/<\/script>/d' inputfile
答案 1 :(得分:1)
此awk
脚本将查找<script*>
标记,设置in
变量,然后阅读下一行。找到结束</script*>
标记时,变量设置为零。如果in
变量为零,则最终打印模式输出所有行。
awk '/<script.*>/ { in=1; next }
/<\/script.*>/ { if (in) in=0; next }
{ if (!in) print; } ' $1
答案 2 :(得分:0)
正如您所提到的,问题是sed
逐行处理输入。
因此,最简单的解决方法是将输入设为单行,例如用输入中不存在您确信的字符替换换行符。
人们很想使用tr
:
… |tr '\n' '_'|sed 's~<script>.*</script>~~g'|tr '_' '\n'
然而“currently tr
fully supports only single-byte characters”,为了安全起见,您可能想要使用ˇ
之类的不可能的字符,而tr
对此无效。
幸运的是,使用sed
,using branching可以实现同样的目标。
回到我们的<script>…</script>
示例,这确实有效,并且(根据之前的链接)跨平台:
… |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~<script>.*</script>~~g
删除了需要删除的内容(请注意,实际使用时需要一些安全保护:因为它会删除第一个<script>
和最后一个</script>
之间的所有内容;此外,请注意,我使用了~
而不是/
来避免在</script>
中转义斜杠:我可以使用几乎任何单字节字符,除了一些保留的字符,例如{{1} }); \
读取换行符。