우분투의 많은 파일에서 ^ L 코드를 어떻게 변경합니까?


8

50000 개가 넘는 많은 XML 파일이 있습니다.

일부 XML 파일에서 일부 파일은 다음과 같이 작성됩니다

<filename>abc.JPEG<^Lilename>

^L하나의 문자이지만 ^LGoogle에서 의미하는 바를 찾을 수 없습니다 .

cat파일의 내용을 인쇄 할 때 다음과 같이 표시됩니다

<filename>abc.JPEG<
                   ilename>

어쨌든, 나는 변경할 <filename>abc.JPEG<^Lilename><filename>abc.JPEG</filename>

이미 많은 파일에서 단어를 변경하는 명령을 찾았습니다.

find . -exec perl -pi -e 's/[find_word]/[change_word]/g' {} \;

그러나 입력하면 검색어를 인식 할 수 없으므로이 명령은 제 경우에는 작동하지 않습니다 ^L.

어떻게 변경할 수 있습니다 <filename>abc.JPEG<^Lilename><filename>abc.JPEG</filename>많은 파일에?


6
양식 피드 문자로 해석 되는 컨텍스트 <\filename>대신에 누군가가 사용한 것 같습니다 . 이러한 파일의 소스를 추적하고 생성 도구의 문제점을 개발자에게 지적해야합니다. 파일을 수정하기 위해 허용되는 대답은 괜찮습니다. </filename>\f
Hans-Martin Mosner

답변:


17

Control-L (로 ^L표시됨)은 "양식 피드"문자입니다. ASCII에서는 10 진수 값 12 ( L알파벳의 12 번째 문자) 또는 16 진수 값 0c를 갖습니다.

$ printf 'foo\x0cbar\n' | cat -et
foo^Lbar$

$ printf 'foo\x0cbar\n'
foo
   bar

16 진 이스케이프 코드를 지정하여 sed와 같은 도구를 사용하여이를 대체 할 수 있습니다.

$ printf 'foo\x0cbar\n' | sed 's/\x0c//'
foobar

또는 ^L키보드 시퀀스 CTRL+ V CTRL+를 사용하여 직접 작성L

sed 's/CTRL+VCTRL+L//'

귀하의 특정 교체를 위해

$ printf '<\x0cilename\n'
<
 ilename

그때

$ printf '<\x0cilename\n' | sed 's/<\x0c/<\/f/g'
</filename

( g한 줄에 둘 이상의 인스턴스가있는 경우 수정자가 추가됩니다).


제 경우에는 "$ printf '<\ x0cilename \ n'| sed 's / <\ x0c / <\\ f / g'"가 작동하지 않습니다. 그러나 귀하의 답변에 따르면 "$ find. -exec perl -pi -e 's / <\ x0cilename> / <\ / filename> / g'{} \;" 잘 작동합니다. 귀하의 답변에 감사드립니다 :)
Yang

@ 양 미안 나는 방금 슬래시와 백 슬래시를 혼란에 빠뜨렸다는 것을 깨달았다. (지금 수정 됨) 여전히 sed 버전이 작동하지 못하게하는 이유는 확실하지 않습니다.
steeldriver

아주 좋은 답변입니다! find50000 개의 XML 파일을 반복하고 각 파일을 자동으로 처리하고 백업을 수행 한 파일 이 포함되어 있으면 더 좋습니다 .
Kingsley

2

Hans-Martin Mosner가 주석에서 지적했듯이 누군가 XML을 생성 할 때 슬래시 대신 백 슬래시를 사용하는 것으로 보입니다 (또는 <filename>슬래시에 지나치게 열광적 인 Unix-to-Windows 변환기를 통해 전체 섹션을 실행했을 수도 있음 ). \f폼 피드 문자, 일명 U + 0C 또는 ^ L에 대해 거의 사용되지 않는 이스케이프 시퀀스입니다. 따라서 파이프 라인의 나중 단계는 \f리터럴 U + 0C 문자 로 대체되었습니다 .

다행히 U + 0C는 XML 에서 의도적 으로 찾을 수없는 매우 드문 문자입니다 . 그리고에만 있기 때문에 \f(말)와 달리,이 생산하는 것 \g또는 \k뿐만 아니라 수정을 교체 찾기 및 보편적을 </filename>뿐만 아니라 </folder>, </file>그 밖의 또는 아무것도 엉망이있어 그.

이것이 바로 스틸 드라이버의 sed-script가하는 일입니다. 나는 그것을 좀 더 일반적으로 만들었습니다.

sed 's|\x0c|/f|g'

이것은 "(s)의 모든 인스턴스 \x0c(즉, U + 0C)를 /f(g) 전역 적으로 바꾼다는 것을 의미합니다.


2

\fPerl의 양식 피드 문자입니다. 이 잘못된 파일은 Perl과 XML을 처음 접하는 사람이 만든 것처럼 보입니다.

여기에는 Perlier 수정 사항이 많이 있습니다. sed로 허용되는 답변과 달리 모든 파일의 업데이트를 자동화하는 OP의 목표를 충족합니다 find.

\f16 진수 코드 대신 간단하게 사용할 수 있습니다 x0c.

find . -type f -exec perl -pi.bkp -e 's [ \f ilename ][ /f ilename ]gx' {} \;

여기에 일반 파일 만 반환 -type f하도록 tel find에 추가 했습니다. 그렇지 않으면 목록으로 find돌아가서 .편집하려고 할 때 경고가 트리거되지만 다른 모든 것은 여전히 ​​작동합니다.

또한 x실제 공백을 무시 하는 플래그를 사용하여 정규식을 쉽게 볼 수 있도록하여 정규식의 요소를 간격을 둘 수 있습니다. 당신이 이것을 좋아하지 않으면, 여기없는 것입니다 :

find . -type f -exec perl -pi.bkp -e 's[\filename][/filename]g' {} \;

그리고 모든 폼 피드 문자가 의심스럽고 모두로 교체해야 /f할 경우 한 줄짜리를 더 얇게 만들 수 있습니다.

find . -type f -exec perl -pi.bkp -e 's[\f][/f]g' {} \;

s///Perl에서 정규식 대체 명령 요소 ( ) 를 둘러싸 기 위해 슬래시를 사용할 필요는 없습니다 . 모든 기호를 사용할 수 있습니다. 그러나 어떤 종류의 대괄호와 같은 기호를 사용하기로 선택한 경우에는 두 가지를 모두 사용해야 s[old][new]합니다.

슬래시를 사용하지 않으므로 슬래시를 벗어날 필요가 없습니다.

as -i.bkp: : perl -pi -e당신은 그 자리에서 편집 할 수 있습니다-그러나 찾기 및 바꾸기 Perl 프로그램이 잘못되었을 때 추가 보험을 원한다면 파일 확장자를 넣어 원본 파일의 사본을 만들 수 있습니다 당신. 여기에을 사용했습니다 .bkp.

최신 버전의 Perl에서 시스템의 전원 손실 또는 디스크 공간 부족과 같은 심각한 문제가 발생할 경우 내부 편집 기능이보다 탄력적으로 업데이트되었습니다. 최근 Perls의 향상된 내부 편집 기능에 대한 Perl 작성자 brian d foy가 있습니다.

이러한 종류의 작업에 Perl을 사용하는 것을 고려해야합니다. 이는 매우 강력하지만 과소 평가 된 범용 프로그래밍 언어이기 때문에 원래의 디자인 목표는 대체 sed하고 awk훨씬 더 나은 것으로 설계되었습니다 .

펄 5의 정규식 매칭 기능과 개선 된 정규식 구문은 지금까지의 그 초과 sed, awk펄 간단하고 고급 정규식 조작 모두를위한 가장 현명한 선택하게 떨어져 펄 6에서, 실제로 다른 모든 프로그래밍 언어를.

명확히하기 위해 : sed제대로 작동 find하고 sed -i.bkp편집 한 각 파일의 백업을 만드는 데 사용할 수도 있지만, 내가 아는 한 Perl 5.28 이상의 추가 복원력은 없습니다. 또한 복잡하고 훨씬 덜 강력한 기존 UNIX ® 정규식 구문을 사용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.