我用来awk
删除文件中的重复项,问题是如果发现重复项,我想删除一组行,例如-
<p>
This is duplicate.
</p>
<p>
This is original.
</p>
<p>
This is duplicate.
</p>
我想把它改成——
<p>
This is duplicate.
</p>
<p>
This is original.
</p>
当一行重复时,删除上一行和下一行,任何帮助将不胜感激。
我目前正在使用-
awk -i inplace '!seen[$0]++' name_of_file
删除重复的行,但我无法弄清楚如何删除上一行和下一行。
答案1
我认为您真正想做的是删除重复的<p>...</p>
分隔记录而不是单独的行。鉴于您发布的示例,这就是 GNU awk (您已经将其用于-i inplace)
多字符 RS:
$ awk 'BEGIN{RS=ORS="</p>\n"} !seen[$0]++' file
<p>
This is duplicate.
</p>
<p>
This is original.
</p>
请注意,无论记录中有多少行,这都有效<p>...</p>
,例如,给定此输入,其中重复记录是多行:
$ cat file
<p>
This
is
duplicate.
</p>
<p>
This is original.
</p>
<p>
This
is
duplicate.
</p>
该脚本仍然删除重复项:
$ awk 'BEGIN{RS=ORS="</p>\n"} !seen[$0]++' file
<p>
This
is
duplicate.
</p>
<p>
This is original.
</p>
答案2
awk
不是解析xml
/html
数据的正确工具,输入格式稍有变化就会失败。
最好使用一些指定的解析器,例如BeautifulSoup
来自python
:
#!/usr/bin/env python3
from bs4 import BeautifulSoup
with open('file.html') as f:
content = f.read()
soup = BeautifulSoup(content, "html.parser")
p_contents=[]
for p in soup.find_all('p'):
p_content = p.get_text().strip()
if p_content in p_contents:
p.extract()
else:
p_contents.append(p_content)
print(soup)
使用awk
:
awk -v start="<p>" -v end="</p>" '
$0 == start { tag=$0; in_tag=1 }
!in_tag
in_tag && ( $0 != start && $0 != end ) { tag=tag"\n"$0 }
$0 == end { if (!seen[tag]++) { print tag"\n"$0 }; in_tag=0 }
' file.html
答案3
事实是:我不知道如何在awk
.和sed
你一起可以做到
sed 'N;/\n</{P;D;};G;/\(\n[^<]*\n\).*\1/{N;d;};s/\n\n.*//;s/\n$//;H' file
这个想法是使用一个N;P;D
循环来始终一起处理两条线。如果第二个不是标语,请测试保留空间中保留的行是否重复。d
删除重复项并将新的原件附加到H
旧空间以供将来参考。
请先在没有选项的情况下进行测试-i
,以免弄乱您的文件。如果它有效并且sed
解决方案适合您,我将添加更详细的解释。