bash - \x0d\x20이 줄을 삭제하는 이유는 무엇입니까?

bash - \x0d\x20이 줄을 삭제하는 이유는 무엇입니까?

이것은 gedit 편집기의 보기입니다: 여기에 이미지 설명을 입력하세요.

그리고 vim 편집기의 보기: 여기에 이미지 설명을 입력하세요.

그런 다음 Tog 대신 Log를 사용하면 grep을 시도하지만 성공적으로 grep하지만 출력이 손상됩니다.

[xiaobai@xiaobai grep]$ grep  Tog test
[xiaobai@xiaobai grep]$ grep  Log test
                               Dtring.valueOf
[xiaobai@xiaobai grep]$ 

그런 다음 파일을 살펴보니 파일도 손상되었습니다.

[xiaobai@xiaobai grep]$ cat test 
                               Dtring.valueOf
[xiaobai@xiaobai grep]$ 

그래서 저는 16진수 덤프를 사용합니다.

[xiaobai@xiaobai grep]$ hexdump -C test 
00000000  4c 6f 67 2e 64 28 22 6d  75 73 69 63 22 2c 20 22  |Log.d("music", "|
00000010  4e 41 56 49 47 41 54 4f  52 3a 20 22 20 2b 20 53  |NAVIGATOR: " + S|
00000020  74 72 69 6e 67 2e 76 61  6c 75 65 4f 66 0d 20 20  |tring.valueOf.  |
00000030  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
00000040  20 20 20 20 20 20 20 20  20 20 20 20 20 44 0d 0a  |             D..|
00000050
[xiaobai@xiaobai grep]$ 

나는 그것을 다음과 같이 좁혔습니다.

[xiaobai@xiaobai grep]$ cat test3
                               D
[xiaobai@xiaobai grep]$ hexdump -C test3
00000000  61 0d 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |a.              |
00000010  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
00000020  20 44 0d 0a                                       | D..|
00000024
[xiaobai@xiaobai grep]$ echo -e '\x61'
a
[xiaobai@xiaobai grep]$ echo -e '\x61\x0d'
a
[xiaobai@xiaobai grep]$ echo -e '\x61\x0d\x20'

[xiaobai@xiaobai grep]$ echo -e '\x61\x0d\x20\x62'
 b

보시다시피 \x20바이트를 추가한 후에 'a'가 제거됩니다.

그래서 내 질문은 왜 이런 일이 발생하며 일부 파일에 \x0d\x20 (예: grep -r )이 포함될 수 있다는 사실을 미리 알지 못한 채 제거하는 방법입니다.

답변1

ASCII 코드의 문자 0~31은 제어 문자입니다. 터미널로 전송되면 특별한 작업을 수행하는 데 사용됩니다. 예를 들어 \a(BEL, 0x7)은 터미널 벨을 울립니다. \b(BS, 0x8) 커서를 뒤로 이동합니다. \n(LF, 0xa)는 커서를 한 줄 아래로 이동하고, \t(TAB 0x9)는 커서를 다음 테이블로 이동합니다.

\r(CR, 0xd) 커서를 첫 번째 열로 이동합니다.

터미널의 쉘 프롬프트에서 실행하는 경우:

printf 'foo\nbar\n'

printf기록되면 장치의 tty 라인 규칙이 이를 변환하므로 foo\nbar\n뒤에 다음 라인이 표시됩니다./dev/tty<something>foo\r\nbar\r\nbarfoo

printf 'foo\rbar\n'

foo터미널을 다음 과 같이 덮어쓰게 됩니다 bar.

파일에 제어 문자가 포함된 경우 해당 문자를 제거하거나 ^M해당 문자가 있는지 확인하려면 텍스트 표현(예: CR 0xd 문자)을 제공할 수 있습니다.\r

그러나 LF 및 TAB 문자에 대해서는 이 작업을 수행하고 싶지 않을 것입니다. 그래서:

LC_ALL=C tr -d '\0-\10\13-\37\177' < file # to remove them

cat -v < file # to display as ^M

sed -n l < file # to display as \r (also converts TAB to \t)
                # and marks the end of lines with $

이들 sedcat해당 항목은 ASCII가 아닌 문자도 변환합니다. 다음을 수행할 수 있습니다.

LC_ALL=C sed "$(printf 's/[^\t -\176\200-\377]/^&/g')" < file |
  LC_ALL=C tr '\0-\10\13-\37\177' '@-HK-_?'

ASCII 제어 문자(TAB 및 LF 제외)만 시각적 형식으로 변환됩니다 ^X(그러나 모든 구현이 NUL 문자가 포함된 입력 파일을 지원하는 것은 아닙니다 sed).

답변2

\x0d\r커서를 줄의 시작 부분으로 가져간 다음 \x20공백을 가져오는 문자이므로 a공백으로 덮어쓰게 됩니다. unix-y 시스템을 사용하는 경우 \r텍스트 출력에 사용되는 경우 필요하지 않으므로 출력/파일에서 제거하는 것을 고려할 수 있습니다 . \n*nix에서는 작동하지만 Windows에서는 작동하지 않음을 "암시"합니다 .

관련 정보