각 단어(태그)가 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 파서를 사용하는 것입니다. 그러나 이 경우 다음 방법을 사용하면 해결 방법이 될 수 있습니다.
파일에서 빈 줄을 모두 제거합니다.
sed -i '/^\s*$/d' file
각 항목 앞에 빈 줄을 추가합니다
<doc>
.sed -i 's/<doc/\n\n<doc/' file
"줄"이 "단락"(빈 줄 앞에 텍스트 부분)으로 정의되는 사용자 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>
플래그가 아직 설정되어 있는지 확인하고, 그렇다면 버퍼를 표시합니다. 마지막으로 플래그 설정 여부에 관계없이 각 줄이 버퍼에 추가됩니다.