특정 문자열 찾기 및 전체 구조 삭제

특정 문자열 찾기 및 전체 구조 삭제

각 단어(태그)가 4개 열로 구성된 별도의 행에 있는 세로 파일이 있습니다. 다음과 같이 문서화된 메타 구조도 있습니다 <doc>.<s>

<doc name="sth" url="http">
<p>
<s>
Here   here   k1gInSc1   here
is   be   k1gMnPc2   be
a  a   k2eAgMnPc1d1   a
sentence   sentence   k1gMnPc1   sentence
<g/>
.       .       kIx.
</s>
</p>
</doc>

문제는 때때로 문자 인코딩이 잘못된다는 것입니다.또는예를 들어 첫 번째 열에서는

<doc name="sth" url="http">
<p>
<s>
Here   here   k1gInSc1   here
is   be   k1gMnPc2   be
Ă  Ă   k?   Ă
sentence   sentence   k1gMnPc1   sentence
<g/>
.       .       kIx.
</s>
</p>
</doc>

이러한 문자를 찾아서 전체 문서 구조를 제거해야 합니다. 그래서 내가 찾으면<doc...>한 줄에서 모든 줄 사이의 모든 항목을 삭제해야 합니다 </doc>.

내 파일에는 10억 줄이 있으며 그 중 약 수천 줄에는 잘못 인코딩된 문자가 포함되어 있습니다.

나는 grep을 사용하여 잘못된 문자를 찾습니다.

xzcat file.vert.xz | grep -i "Ă\|Ĺ\|ľ\|ş\|Ä" > file_bad_characters.txt

어떻게 이러한 문자를 감지하고 해당 줄뿐만 아니라 <doc>구조 사이의 전체 텍스트를 삭제할 수 있습니까?

답변1

올바른 접근 방식은 적절한 XML 파서를 사용하는 것입니다. 그러나 이 경우 다음 방법을 사용하면 해결 방법이 될 수 있습니다.

  1. 파일에서 빈 줄을 모두 제거합니다.

    sed -i '/^\s*$/d' file
    
  2. 각 항목 앞에 빈 줄을 추가합니다 <doc>.

    sed -i 's/<doc/\n\n<doc/' file 
    
  3. "줄"이 "단락"(빈 줄 앞에 텍스트 부분)으로 정의되는 사용자 Perl의 "단락 모드":

    perl -00 -ne 'print unless /[ĂĹľşÄ]/' file > newfile
    

    또는 원본 파일을 바꾸려면 다음을 수행하십시오.

    perl -i.bak -00 -ne 'print unless /[ĂĹľşÄ]/' file
    

중요한<doc...: 모든 것이 태그 내에 있는 잘 구조화된 파일을 가정합니다 .

답변2

유감스럽게도 이는 grep만으로는 수행할 수 없는 작업입니다. grep이 제공할 수 없는 행에 대한 일부 컨텍스트를 유지해야 합니다. 그러나 이를 수행할 수 있는 다른 여러 언어가 있습니다. 예는 다음과 같습니다 awk.

awk '/<doc>/ {text=""; output=1}
     /Ă|Ĺ|ľ|ş|Ä/{output=0}
     {text = text $0 "\n"}
     /<\/doc>/ {if(output==1){printf "%s", text}}"

이는 버퍼를 생성하고, text입력에서 토큰을 볼 때 호출되며, 인쇄할 텍스트를 나타내는 플래그를 설정합니다. <doc>금지된 문자를 만나면 플래그가 지워집니다. token 을 만나면 </doc>플래그가 아직 설정되어 있는지 확인하고, 그렇다면 버퍼를 표시합니다. 마지막으로 플래그 설정 여부에 관계없이 각 줄이 버퍼에 추가됩니다.

관련 정보