如何在图案重复时删除图案之间的线条
How to delete lines between a pattern when the pattern repeats
有一个很大的 HTML
文档,其中 BEGIN
和 END
的术语在整个文档中重复出现。
例如,BEGIN 为 <script>
,END 为 </script>
。
对于文档中模式的每个实例,模式之间有可变数量的行(在 <script>
和 </script>
之间)。
已在 sed
中尝试过以下方法:
sed '/\<script>/,/\<\/script>/d'
这个 sed
字符串删除第一次出现的 <script>
和 最后一次 出现的 </script>
之间的所有内容。
也尝试过:
awk '/\<script>/,/\<\/script>/d'
这个 awk
字符串会删除模式之间的所有内容,但与 sed 字符串不同的是,它会保留每次出现的模式,如下所示:
<script>
</script>
总而言之,我可以得到我想要的变体(或相反的变体)。
- sed 删除模式(的一个实例)之间的文本
- awk 保留模式的所有出现,但删除模式之间的内容,以及模式前后的内容。
我的问题:使用 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'
据我了解您的问题,您想删除(如您所述)BEGIN
和 END
之间的所有行,保留行 BEGIN
和 END
.
如果是这样,这应该适合您:
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
有一个很大的 HTML
文档,其中 BEGIN
和 END
的术语在整个文档中重复出现。
例如,BEGIN 为 <script>
,END 为 </script>
。
对于文档中模式的每个实例,模式之间有可变数量的行(在 <script>
和 </script>
之间)。
已在 sed
中尝试过以下方法:
sed '/\<script>/,/\<\/script>/d'
这个 sed
字符串删除第一次出现的 <script>
和 最后一次 出现的 </script>
之间的所有内容。
也尝试过:
awk '/\<script>/,/\<\/script>/d'
这个 awk
字符串会删除模式之间的所有内容,但与 sed 字符串不同的是,它会保留每次出现的模式,如下所示:
<script>
</script>
总而言之,我可以得到我想要的变体(或相反的变体)。
- sed 删除模式(的一个实例)之间的文本
- awk 保留模式的所有出现,但删除模式之间的内容,以及模式前后的内容。
我的问题:使用 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'
据我了解您的问题,您想删除(如您所述)BEGIN
和 END
之间的所有行,保留行 BEGIN
和 END
.
如果是这样,这应该适合您:
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