SED에서 [모든 기호]를 지정하는 방법은 무엇입니까?

SED에서 [모든 기호]를 지정하는 방법은 무엇입니까?

매우 큰 텍스트 파일에서 외국어 및 기타 키보드가 아닌 문자를 제거하기 위해 SED 명령을 사용하고 있습니다.

예:

sed 's/[^a-zA-Z0-9]//g'

위 명령은 내가 원하는 것과 가까운 영숫자 문자만 포함하는 모든 줄을 유지합니다. 문제는 !@#$% 등과 같은 일반적인 기호가 포함된 줄도 제거한다는 것입니다. 나는 그것들을 간직하고 싶다. !-)와 같은 금괴 명령을 검색해 보았습니다. 하지만 비슷한 것을 찾을 수 없습니다.

그렇다면 목록에서 아랍어, 러시아어 및 입력할 수 없는 문자를 필터링하는 방법은 무엇입니까? (이상적으로는 캐릭터에만 핵폭탄을 쏘고 싶지 않고 캐릭터가 발견된 행 전체에 핵폭탄을 쏘고 싶습니다.)

답변1

Kusalananda와 같은 클래스를 사용하는 것 외에도 유니코드를 기반으로 자신만의 범위를 만들 수 있습니다. 확인하다이것은 유니콜드 테이블을 의미합니다.마음에 드는 캐릭터를 찾아보세요. PCRE의 경우 "표준" 문자 + TAB에 가능한 방법은 다음과 같습니다.

 grep -P '^[\x{0020}-\x{007e}\x{0008}]{1,}$' file

\x{000A}grep줄당 기능(표준 모드) 으로 인해 개행 문자는 제어 문자로 포함되지 않습니다. MS 스타일 개행 문자가 영향을 받고 \x{000d}\x{000a}개행 문자에 사용된다는 점을 고려하세요!

답변2

텍스트에서 ASCII가 아닌 문자를 제거하려면 tr다음과 같은 방법을 사용하는 것이 좋습니다.

LC_ALL=C tr -d -c '[:print:][:cntrl:]' <file.in >file.out

두 POSIX 문자 클래스는 [:print:]함께 [:cntrl:]ASCII 범위의 모든 문자를 포괄하므로 이에 대한 보완, 즉 모든 비ASCII 문자를 고려해야 -c합니다 . tr우리는 이 보완 문자를 제거할 -d것을 요청합니다 .tr

문자 클래스가 ASCII 범위 32에서 126 사이의 문자만 일치 하도록 (또는 ) LC_ALL로 설정했습니다 . 그렇지 않으면 로케일의 인쇄 가능한 문자와 일치할 수 있습니다(예: ) . 이 클래스는 0~31 및 127 범위의 문자와 일치합니다. 를 사용하면 이 두 클래스가 함께 ASCII 문자인 0~127을 포함합니다.CPOSIX[:print:]ä[:cntrl:]LC_ALL=C

ASCII가 아닌 문자가 포함된 전체 줄을 삭제하려면:

LC_ALL=C grep -v '[^[:print:][:cntrl:]]' <file.in >file.out

이 표현식은 [^[:print:][:cntrl:]]ASCII가 아닌 단일 문자와 일치합니다. -v쿼리를 사용하여 grep모든 행을 추출합니다.아니요ASCII가 아닌 문자를 포함하지 않는 줄을 추출하는 이 표현식과 일치합니다.

이 두 명령은 다음을 사용하여 수행할 수도 있습니다 sed.

ASCII가 아닌 문자를 제거합니다.

LC_ALL=C sed 's/[^[:print:][:cntrl:]]//g' <file.in >file.out

ASCII가 아닌 문자가 포함된 줄을 삭제합니다.

LC_ALL=C sed '/[^[:print:][:cntrl:]]/d' <file.in >file.out

Stéphane이 지적했듯이댓글에서, 위 명령은 ASCII 문자만 포함하는 텍스트를 반환합니다.또는 최소한 ASCII로 인코딩된 문자(파일 인코딩에 따라 다릅니다.)


완전히 다른 접근 방식은 다음을 사용하는 것입니다 iconv.

iconv -c -t ascii file.in >file.out

그러면 파일이 ASCII 인코딩으로 변환되어 변환할 수 없는 모든 문자(줄 아님)가 자동으로 제거됩니다.

관련 정보