bash 스크립트에서 유니 코드를 grep하는 방법


11
if grep -q "�" out.txt
    then
        echo "working"
    else
        cat out.txt
fi

기본적으로 파일 "out.txt"에 파일의 아무 곳에 나 " "가 포함되어 있으면 "working"을 에코하고 "out.txt"파일에 파일의 "where"가없는 경우 파일을 원합니다 고양이 out.txt에

편집 : 그래서 내가하고있는 일이 있습니다. openssl 암호 해독을 무력화하려고합니다.

openssl enc는 성공하면 0을, 그렇지 않으면 0이 아닌 값을 반환합니다. 참고 : AES / CBC는 패딩을 올바르게 수행하여 "암호 해독이 작동하는지"만 판단 할 수 있으므로 오 탐지가 발생합니다. 따라서 파일이 해독되지만 올바른 암호가 아니므로 횡설수설됩니다. 횡설수설의 일반적인 문자는 " "입니다. 따라서 출력에 " "가 포함되어 있으면 do 루프가 계속 진행되기를 원합니다.

여기 내 자식 링크 https://github.com/Raphaeangelo/OpenSSLCracker 여기 스크립트가 있습니다

while read line
do
openssl aes-256-cbc -d -a -in $1 -pass pass:$line -out out.txt 2>out.txt >/dev/null && printf "==================================================\n"
if grep -q "�" out.txt
    then
        :
    else
        cat out.txt &&
            printf "\n==================================================" &&
            printfn"\npassword is $line\n" &&
            read -p "press return key to continue..." < /dev/tty; 
fi
done < ./password.txt

여전히 charicter로 출력을 보여줍니다.

업데이트 : 해결

printf "Working..."

while read line
do
openssl aes-256-cbc -d -a -in $1 -pass pass:$line -out out.txt 2>out.txt >/dev/null
if file out.txt | grep -q 'out.txt: ASCII text'
    then
        printf "\n==================================================\n\n" &&
            cat out.txt &&
            printf "\n==================================================" &&
            printf "\npassword is $line\n" && 
            read -p "press return key to continue..." < /dev/tty;
    else
        : 
fi
done < ./password.txt

그것은 올바르게 보이고 작동해야합니다 (btw, 유니 코드 문자를 볼 수있는 글꼴이 없지만 특별한 의미는 없습니다). greplong은 유니 코드를 이해합니다 (아주 문자열을 검색 LANG=C grep하면 성능이 크게 향상 되므로 속도가 훨씬 느려집니다 ).
peterh-복원 모니카

여기의 모든 사람을 완전히 혼란스럽게 생각하기 때문에 이것을 삭제하고 다른 질문을 게시해야 할 수도 있습니다.
스튜어트 슬론

@Stuart Sloan 질문의 제목 How to grep for unicode � in a bash script은 이것이 정말로 당신이 원하는 것입니까? 유니 코드를 추출하려면? 우리가 도울 수 있도록 명확히하십시오!

1
@Goro 원본 게시물을 수정했습니다. 나는 그것이 의미가 있기를 바랍니다. 그렇지 않은 경우 알려 주시면 명확하게 시도하겠습니다.
스튜어트 슬론

1
현재의 두 가지 대답은 매우 오도됩니다. 내 답변을 읽고 (다시) 두 답변 모두 잘못되었다는 것을 설명하기 위해 편집했습니다.
Isaac Isaac

답변:


27

grep 작업에 대한 잘못된 도구입니다.

당신은 U+FFFD REPLACEMENT CHARACTER문자 그대로 파일 내용에 있기 때문에가 아니라 텍스트 기반 입력 만 처리하는 도구로 바이너리 파일을 보았 기 때문에 를 볼 수 있습니다 . 유효하지 않은 입력 (예 : 임의의 이진 데이터)을 처리하는 표준 방법은 현재 로케일에서 유효하지 않은 모든 항목 (대개 UTF-8)을 화면에 치기 전에 U + FFFD로 바꾸는 것입니다.

즉, 파일에서 리터럴 \xEF\xBF\xBD(U + FFFD 문자의 UTF-8 바이트 시퀀스)이 발생하지 않을 가능성이 매우 높습니다 . grep당신에게 말하는데 완전히 옳습니다.

파일에 알려지지 않은 바이너리가 포함되어 있는지 감지하는 한 가지 방법은 다음 file(1)명령을 사용하는 것입니다.

$ head -c 100 /dev/urandom > rubbish.bin
$ file rubbish.bin
rubbish.bin: data

알 수없는 파일 형식의 경우 간단히 말합니다 data. 시험

$ file out.txt | grep '^out.txt: data$'

파일에 실제로 임의의 이진 파일이 포함되어 있는지 여부를 확인합니다.

이것이 out.txtUTF-8로 인코딩 된 텍스트 파일 인지 확인 하려면 iconv다음을 대신 사용할 수 있습니다 .

$ iconv -f utf-8 -t utf-16 out.txt >/dev/null

당신은 정확히 맞습니다! 불행히도, 나는 여전히 출력에서 ​​약간의 쓰레기를 받고 있습니다.
스튜어트 슬론

아마도 file그 파일에 대한 몇 가지 다른 콘텐츠 유형을 감지합니다. 100 %가 항상 UTF-8로 인코딩 된 텍스트 파일 만 기대 iconv하는 경우 파일이 유효한 UTF-8인지 확인하십시오 iconv -f utf-8 -t utf-16 out.txt >/dev/null. 경우 iconv유효하지 않은 UTF-8 시퀀스로 파일을 변환 할 수 없습니다, 그것은 0이 아닌 종료 코드를 반환합니다.
Boldewyn

2
파일 명령이 맞았습니다! 문제를 해결해 주셔서 감사합니다.
스튜어트 슬론

4
물론 grep은 "작업을위한 도구"입니다 grep -axv '.*' badchars.txt. 유효하지 않은 유니 코드 문자 가 포함 된 행을 인쇄합니다 .
Isaac

1
이것은 매우 오해의 소지가 있으므로 내 답변에서 무엇을하는지 읽으십시오 file.
Isaac

5

TL; DR :

grep -axv '.*' out.txt 

긴 대답

현재의 두 가지 대답은 매우 오도되고 기본적으로 잘못되었습니다.

테스트하려면 다음 두 파일을 가져 오십시오. (저명한 개발자 : Markus Kuhn) :

$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-demo.txt
$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt

데모

첫 번째 UTF-8-demo.txt는 UTF-8이 많은 언어, 수학, 점자 및 기타 유용한 유형의 문자를 얼마나 잘 표현할 수 있는지 보여주기 위해 설계된 파일입니다. utf-8을 이해하는 텍스트 편집기로 살펴보면 많은 예제와 no가 표시 됩니다.

문자 범위를 제한 \x00-\x7F하여이 파일 내부의 거의 모든 것을 거부 할 수 있습니다.
그것은 매우 잘못 되었으며 해당 파일에 아무것도 없으므로 제거하지 않습니다 .

해당 답변에서 권장되는 테스트를 사용하면 72.5 %파일 이 제거 됩니다.

$ grep -oP "[^\x00-\x7F]" UTF-8-demo.txt | tr -d '\n' | wc -c
10192
$ cat UTF-8-demo.txt | wc -c
14058

그것은 (가장 실용적인 목적으로) 전체 파일입니다. 완벽하게 유효한 문자를 표시하도록 매우 잘 설계된 파일입니다.

테스트

두 번째 파일은 utf-8 리더가 잘 작동하고 있는지 확인하기 위해 여러 가지 경계 사례를 시도하도록 설계되었습니다. 내부에 ' '가 표시되는 많은 문자가 포함되어 있습니다. 그러나 사용할 다른 답변 권장 사항 (선택된 답변) file이이 파일에서 크게 실패합니다. 0 바이트 ( \0) (기술적으로 유효한 ASCII) 및 \x7f바이트 (DEL-delete) (명확하게 ASCII 문자 임) 만 제거하면 모든 파일이 file명령에 유효합니다 .

$ cat UTF-8-test.txt | tr -d '\0\177' > a.txt
$ file a.txt 
a.txt: Non-ISO extended-ASCII text, with LF, NEL line terminators

많은 잘못된 문자 file를 감지 하지 못할 뿐만 아니라 UTF-8로 인코딩 된 파일임을 감지하여보고 하지도 않습니다 .

예, fileUTF-8로 인코딩 된 텍스트를 감지하고보고 할 수 있습니다.

$ echo "ééakjfhhjhfakjfhfhaéá" | file -
/dev/stdin: UTF-8 Unicode text

또한 file1-31 범위의 대부분의 제어 문자를 ASCII로보고하지 않습니다. ( file)는 일부 범위를 data다음 과 같이보고합니다 .

$ printf '%b' "$(printf '\\U%x' {1..6})" | file -
/dev/stdin: data

기타 ASCII text:

$ printf '%b' "$(printf '\\U%x' 7 {9..12})" | file -
/dev/stdin: ASCII text

인쇄 가능한 문자 범위 (줄 바꾸기 포함) :

$ printf '%b' "$(printf '\\U%x' {32..126} 10)" | file -
/dev/stdin: ASCII text

그러나 일부 범위는 이상한 결과를 초래할 수 있습니다.

$ printf '%b' "$(printf '\\U%x' {14..26})" | file -
/dev/stdin: Atari MSA archive data, 4113 sectors per track, starting track: 5141, ending track: 5655

이 프로그램 file은 텍스트를 감지하는 도구가 아니라 실행 가능한 프로그램이나 파일에서 마법의 숫자 를 감지하는 도구 입니다.

범위가 file감지되었으며 내가 찾은 해당 유형은 다음과 같습니다.

  • 1 바이트 값, 주로 ASCII :

    {1..6} {14..26} {28..31} 127   :data
    {128..132} {134..159}          :Non-ISO extended-ASCII text
    133                            :ASCII text, with LF, NEL line terminators
    27                             :ASCII text, with escape sequences
    13                             :ASCII text, with CR, LF line terminators
    8                              :ASCII text, with overstriking
    7 {9..12} {32..126}            :ASCII text
    {160..255}                     :ISO-8859 text
    
  • UTF-8 인코딩 범위 :

    {1..6} {14..26} {28..31} 127   :data
    27                             :ASCII text, with escape sequences
    13                             :ASCII text, with CR, LF line terminators
    8                              :ASCII text, with overstriking
    7 {9..12} {32..126}            :ASCII text
    {128..132} {134..159}          :UTF-8 Unicode text
    133                            :UTF-8 Unicode text, with LF, NEL line terminators
    {160..255}                     :UTF-8 Unicode text
    {256..5120}                    :UTF-8 Unicode text
    

가능한 해결책은 다음과 같습니다.


이전 답변.

게시하는 문자의 유니 코드 값은 다음과 같습니다.

$ printf '%x\n' "'�"
fffd

예, 이는 유니 코드 문자 'REPLACEMENT CHARACTER'(U + FFFD) 입니다. 텍스트에서 발견 된 유효하지 않은 유니 코드 문자 를 대체하는 데 사용되는 문자입니다. 그것은 실제적인 성격이 아니라 "시각적 원조"입니다. 잘못된 유니 코드 문자 가 포함 된 모든 전체 줄을 찾아서 나열하려면 다음을 사용하십시오.

grep -axv '.*' out.txt 

그러나 문자가 유효하지 않은 경우에만 감지하려면 다음을 사용하십시오.

grep -qaxv '.*' out.txt; echo $?

결과가 1파일이 깨끗하면 0이됩니다 0.


당신이 요구 한 것이 문자 를 찾는 방법 이라면, 이것을 사용하십시오 :

➤ a='Basically, if the file "out.txt" contains "�" anywhere in the file I'
➤ echo "$a" | grep -oP $(printf %b \\Ufffd)
�

또는 시스템이 UTF-8 텍스트를 올바르게 처리하는 경우 간단히 다음을 수행하십시오.

➤ echo "$a" | grep -oP '�'
�

세상에 정말 고마워요 grep -axv '.*' !! 나는 텍스트 파일에 몇 가지 나쁜 문자와 10 ~ 2 년 동안 emacs에서 수정하는 방법으로 어려움을 겪었습니다!
nealmcb

3

이 초기 답변은 원래 게시물에 대한 것이 었습니다.

bash 스크립트에서 유니 코드를 grep하는 방법

if grep -q "�" out.txt
    then
        echo "working"
    else
        cat out.txt  fi

기본적으로 파일 "out.txt"에 파일의 아무 곳에 나 " "가 포함되어 있으면 "working"을 에코하고 "out.txt"파일에 파일의 "where"가없는 경우 파일을 원합니다 고양이 out.txt에

시험

grep -oP "[^\x00-\x7F]"

if .. then다음과 같이 문 :

if grep -oP "[^\x00-\x7F]" file.txt; then
    echo "grep found something ..."
else
    echo "Nothing found!"
fi

설명 💡 :

  • -P, --perl-regexp: PATTERN은 Perl 정규식입니다.
  • -o, --only-matching: PATTERN과 일치하는 줄의 일부만 표시
  • [^\x00-\x7F] 단일 비 ASCII 문자와 일치하는 정규식입니다.
  • [[:ascii:]] -단일 ASCII 문자와 일치
  • [^[:ascii:]] -단일 비 ASCII 문자와 일치

bash

LC_COLLATE=C grep -o '[^ -~]' file

3
누군가 영어를하지 못하는 즉시 깨질 것입니다.
Kevin

또는 누군가가 일품 요리, 그림 이모티콘, 포켓몬 또는 7 비트 ASCII로 엄격하게 제한되지 않은 것을 논의하려고하는 경우. 09 0A 0D (탭, 줄 바꿈, 캐리지 리턴)를 제외하고 00-1F의 항목을 더 잘 찾으십시오.
Alcaro

이것은 매우 나쁜 생각입니다. 이것은 거부합니다 어떤 아스키 범위 위의 유효한 유니 코드 문자, 단지 조금 밖에 백만 명 이상의 유효한 문자. 놀랄 만한. 시도 : printf '%b' "$(printf '\\U%x' {128..131})" | grep -oP "[^\x00-\x7F]"코드가 거부하는 유효한 유니 코드 문자는 4 개뿐입니다. :-(
Isaac Isaac

이것은 매우 잘못된 답변입니다. ASCII로만 제한하는 단순한 접근 방식이 크게 실패한 이유는 제 대답에서 읽으십시오 .
Isaac
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.