如何在图案重复时删除图案之间的线条

How to delete lines between a pattern when the pattern repeats

有一个很大的 HTML 文档,其中 BEGINEND 的术语在整个文档中重复出现。 例如,BEGIN 为 <script>,END 为 </script>。 对于文档中模式的每个实例,模式之间有可变数量的行(在 <script></script> 之间)。

已在 sed 中尝试过以下方法:

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

这个 sed 字符串删除第一次出现的 <script> 最后一次 出现的 </script> 之间的所有内容。

也尝试过:

awk '/\<script>/,/\<\/script>/d'

这个 awk 字符串会删除模式之间的所有内容,但与 sed 字符串不同的是,它会保留每次出现的模式,如下所示:

<script>
</script>

总而言之,我可以得到我想要的变体(或相反的变体)。

我的问题:使用 sed 或 awk(and/or 任何其他 GNU 实用程序),当术语定义模式时如何删除模式之间的内容( BEGIN 个术语和 END 个术语)在文档中出现多次?

sed 适合我。您确定它删除了第一次和最后一次出现之间的所有内容吗?

for i in {1..20} ; do
    echo $i
    (( 0 == i % 7 )) && echo '<script>'
    (( 0 == i % 8 )) && echo '</script>'
done | sed '\=<script>=,\=</script>=d'

输出:

1
2
3
4
5
6
7
9
10
11
12
13
14
17
18
19
20

要查看删除的部分,请在 d:

之前添加一个 !
... | sed '\=<script>=,\=</script>=!d'
<script>
8
</script>
<script>
15
16
</script>

试试:

awk '/<script>/,/<\/script>/{next}1' 

据我了解您的问题,您想删除(如您所述)BEGINEND 之间的所有行,保留行 BEGINEND. 如果是这样,这应该适合您:

sed  '/\<script>/,/\<\/script>/ { /<script>/n; /\<\/script>/ !{ d; }; }' input_file

输入:

<html>
 <head>
 <title></title>
<body>
 <script>
SOME SCRIPT
</script>
 <script>
SOME OTHER SCRIPT
 </script>
</head>
</body>
</html>

输出:

<html>
 <head>
 <title></title>
<body>
 <script>
</script>
 <script>
 </script>
</head>
</body>
</html>

另一种 awk 替代方法

awk '/\<script/{p=1};/\/script/{p=0;;next}; !p' file.html
$ cat file
a
<script>
b
</script>
c
<script>
d
</script>
e

$ awk '/<script>/{f=1} !f; /<\/script>/{f=0}' file
a
c
e