워크 플로우 (파일)에서 ASCII가 아닌 모든 문자 제거


13

하나의 파일에서 ASCII가 아닌 모든 문자를 어떻게 제거합니까? 이를 수행하기위한 특정 명령이 있습니까?

grep --colour='auto' -P -n'[^\x00-\x7]' /usr/local/...

나는 이것이 워크 플로우 내에서 문자를 찾는다고 생각하지만 문제가되는 문자의 모든 인스턴스를 어떻게 제거합니까?



2
관련 : 제어 문자를 사용하여 자동으로 제거하는 대신 문제를 피하려면 cat -vASCII represantation으로 표시하십시오. (. 예를 들어 ^G에 대한 \007)
마티 Nalis

1
"비 ASCII 문자"라고 말할 때 악센트 부호 문자도 포함합니까?
Captain Man

1
@MatijaNalis 표현에 대한 추가 정보 : en.wikipedia.org/wiki/Caret_notation
wjandrea

1
사용 사례는 무엇입니까? 종종 많은 특수 문자를 제거하는 것보다 훨씬 더 효과적인 특정 도구 또는 다른 방법이 있습니다. ASCII에는 세로 탭, 벨 및 NUL과 같은 몇 가지 "특수"문자가 포함되어 있습니다. 인쇄 가능한 문자를 의미하지 않습니까?
l0b0

답변:


26

ASCII 문자는 0에서 177 (8 진수) 사이의 문자입니다 .

파일에서이 범위 밖의 문자를 삭제하려면

LC_ALL=C tr -dc '\0-\177' <file >newfile

tr명령은 단일 문자 에서 작동하는 유틸리티 로 다른 단일 문자로 대체하거나 (음역) 삭제하거나 동일한 문자의 실행을 단일 문자로 압축합니다.

위의 명령은 file에서 수정 된 내용을 읽고 씁니다 newfile. -d에 옵션 tr유틸리티 삭제 자 (대신 그들을 음역의) 차종, 그리고 -c그것은 주어진 간격 (대신 내부의) 외부의 문자를 고려한다.

LC_ALL=C모든 바이트 값이 유효한 문자를 구성하는지 확인하십시오. tr그렇지 않으면 로케일의 문자 인코딩에서 유효한 문자를 형성하지 않는 일련의 바이트를 발견하면 일부 구현이 중단됩니다.


원본 파일을 수정 된 파일로 바꾸려면

LC_ALL=C tr -dc '\0-\177' <file >newfile &&
mv newfile file

새 파일의 이름이 tr성공적으로 완료된 후 이전 파일의 이름으로 바뀝니다 . 경우 tr성공적으로 완료되지 않은 원래 파일을 읽을 수 없습니다 또는 새 파일에 쓸 수 있기 때문에, 하나, 원본 파일은 변경되지 않습니다.

또는 원본 파일의 메타 데이터 (권한 등)를 최대한 보존하려면

cp file tmpfile &&
LC_ALL=C tr -dc '\0-\177' <tmpfile >file &&
rm tmpfile


9

필요한 것이 정규 표현식이라면 [\x00-\x7F]여러 유틸리티에 적용 할 수 있습니다.

<file LC_ALL=C   sed   's/[^\o0-\o177]//g'      # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^\0-\177]/,"");print}'
<file            perl  -pe 's/[^[:ascii:]]//g;'
<file LC_ALL=C   tr    -dc '\0-\177'

sed, awk 및 perl은 Unix에 정의 된 "텍스트 파일"을 기대합니다. 이 경우 모든 것이 잘 작동합니다. 그러나 특히 awk는 소스 파일에 존재하는지 여부에 관계없이 후행 줄 바꿈을 추가합니다 (printf를 사용하면 입력의 모든 줄 바꿈이 제거됩니다). tr은 모든 파일 형식에서 작동하도록 설계되었습니다. 그러나 NUL ( \0)은 POSIX 텍스트 파일 에서 유효한 문자가 아니므 로 피해야합니다.

줄에 NUL 문자가 없습니다 ...

실제로 많은 제어 문자는 특정 조건에서 다른 문제를 발생시킵니다.
그래서 아마도[\x07-\x0d\x20-\x7e]

<file LC_ALL=C   sed   's/[^\o007-\o015\o040-\o176]//g'            # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^\0-\15\40-\176]/,"");print}'
<file            perl  -pe 's/[^\x{7}-\x{d}\x{20}-\x{7e}]//g;'
<file LC_ALL=C   tr    -dc '\7-\15\40-\176'

7-13 범위 (10 진수)는 \a\b\t\n\v\f\r(순서대로)입니다.
비슷한 (아마도 이식성이 좋은) 범위는 [^[:space:][:print:]] (similar because it doesn't include\ a \ b` --bell and backspace--) 로 쓸 수 있습니다 .

<file LC_ALL=C   sed   's/[^[:space:][:print:]]//g'  # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^[:space:][:print:]]/,"");print}'
<file            perl   -pe 's/[^[:space:][:print:]]//g;'
<file LC_ALL=C   tr     -dc '[:space:][:print:]'

관련 :
정규식 ASCII 문자
Perl 솔루션
Posix 텍스트 파일


입력 tr은 텍스트 파일뿐만 아니라 모든 유형의 파일이 될 수 있습니다. awk반면에 텍스트 파일을 가져옵니다.
Kusalananda

"텍스트 파일"이외의 파일을 "아스키 문자 만"이라고 부르는 다른 것을 찾는 것은 매우 어렵습니다 (예, 평신도의 용어로). @Kusalananda (어쨌든 awk에 대한 참고 사항).
NotAnUnixNazi

이것은 gensub()확장 기능입니다. 을 원하고 gsub(...); print16 진수 시퀀스 (및 LC_ALL = C) 대신 8 진수를 사용하여 이식 가능하게하십시오.
Stéphane Chazelas

@ StéphaneChazelas GNU 구문을 특정하게 만드는 GNU sed의 한계는 무엇입니까 (POSIXLY_CORRECT 문제를 이해합니다).
NotAnUnixNazi

[^\o0]POSIX에서 백 슬래시, o 및 0 이외의 문자 sed(GNU sed를 제외한 모든 구현에서) 와 일치하는 것 입니다. 이는 GNU 의 제한 사항sed아니라 비 규격 확장이므로 POSIXLY_CORRECT가 환경에있을 때 비활성화됩니다.)
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.