특정 조건이 충족될 때 awk를 사용하여 행 집합을 삭제하는 방법

특정 조건이 충족될 때 awk를 사용하여 행 집합을 삭제하는 방법

파일에서 중복 항목을 제거하는 데 사용하고 있습니다 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

awkxml구문 분석 / 데이터 에 적합한 도구가 아니며 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솔루션이 효과가 있다면 더 자세한 설명을 추가하겠습니다.

관련 정보