"-c" 옵션과 2 확장자를 설정한 "tr"이 끝에 불필요한 문자를 추가하는 이유는 무엇입니까?

"-c" 옵션과 2 확장자를 설정한 "tr"이 끝에 불필요한 문자를 추가하는 이유는 무엇입니까?

tr문자열에서 "불법" 문자가 모두 "허용" 문자 집합 외부에 있는 "불법" 문자를 대체 문자 (이는 허용되는 문자 세트에 추가됩니다. 그러나 이 -c옵션을 명시적인 *반복 지정자 또는 "세트 2"의 암시적 확장 과 함께 사용하면 tr추가추가의출력용 대체 문자의 인스턴스입니다.

다시 나타나다

  • "허용되는" 문자를 a-n문자 그대로 로 지정합니다 abcdefghijklmn.
  • 대체 문자를 로 둡니다 z.
  • 입력 문자열을 hell또는 로 둡니다 hello. 예상되는 출력 문자열은 then hell및 입니다 hellz.

데모

  1. 잘못된 문자가 존재합니다. 암시적 세트 2 확장자입니다.

    $ echo "hello" | tr -c 'abcdefghijklmn' 'z'
    hellzz
    

    예상되는 출력은 입니다 hellz.

  2. 문자만 허용되며 암시적 세트 2 확장자입니다.

    $ echo "hell" | tr -c 'abcdefghijklmn' 'z'
    hellz
    

    예상되는 출력은 입니다 hell.

  3. 잘못된 문자가 존재합니다. 확장자 2개를 명시적으로 설정했습니다.

    $ echo "hello" | tr -c 'abcdefghijklmn' '[z*]'
    hellzz
    

    예상되는 출력은 입니다 hellz.

  4. 문자만 허용되며 명시적으로 확장자 2개를 설정합니다.

    $ echo "hell" | tr -c 'abcdefghijklmn' '[z*]'
    hellz
    

    예상되는 출력은 입니다 hell.

  5. echo-pipe 대신 here-string을 사용하는 경우에도 동일한 일이 발생합니다(사실 here-string은 제가 이 효과를 처음 발견했을 때 사용한 구성이었습니다).

    $ tr -c 'abcdefghijkl' '[z*]' <<< "hello"
    hellzz
    

tr왜 여기에 하나를 추가 해야 합니까 z?

이것은 Linux에서 bash, UTF-8 로케일을 사용하고 trGNU coreutils 8.25 및 8.30을 사용합니다.

답변1

echo이는 인쇄하라고 지시한 내용의 끝에 개행 문자가 추가되기 때문입니다 . 여기서 문자열을 사용하는 경우에도 마찬가지입니다.

따라서 echo "hello"실제로 인쇄됩니다 hello\n.

$ echo hello | od -c
0000000   h   e   l   l   o  \n
0000006

이것이 바로 당신이 이것을 보는 이유입니다:

$ echo "hell" | tr -c 'abcdefghijklmn' 'z'
hellz$

거기에는 후행 줄 바꿈이 없으며 $내 프롬프트가 마지막에 나타납니다 . 이는 끝에 인쇄된 내용 이 로 대체되기 때문 z입니다 .\nhello\nzprintf

$ printf "hello" | tr -c 'abcdefghijklmn' 'z'
hellz$

( printf %s "$string"임의 문자열의 경우 no printf "$string")

또는 echo이를 지원하는 것을 사용하는 경우 다음을 사용하십시오 echo -n.

$ echo -n "hello" | tr -c 'abcdefghijklmn' 'z'
hellz$

echo또는 표준 UNIX (및 옵션이 모두 활성화된 경우 내장된 것과 같은 ) 가 있는 경우 echo출력을 중지하는 원인을 사용하십시오.bashposixxpg_echo\cecho

$ echo 'hello\c' | tr -c 'abcdefghijklmn' 'z'
hellz$

그러나 출력이 여전히 올바른 텍스트가 되도록 입력에 해당 줄 구분 기호를 유지하려고 할 가능성이 높습니다.

printf '%s\n' "$string" | tr -c 'abcdefghijklmn\n' '[z*]'

(대신 표준 POSIX 구문이 사용되어 줄 바꿈을 더 명확하게 printf추가 echo하고 문자로 시작 -하거나 문자를 포함하는 \문자열과 관련된 문제를 방지합니다.)

tr또한 구현 에 따라 개별적으로 문자로 디코딩할 수 없는 바이트가 남을 수 있지만(변경되지 않음 z) 일부 다른 경우(예: GNU)에서는 tr문자당 단일 문자(및 로케일 세트) 바이트가 있는 텍스트에 대해서만 작동합니다.

sed또 다른 접근 방식은 적어도 GNU 구현에서는 이와 관련하여 더 잘 작동하는 방법을 사용하는 것입니다 .

sed 's/[^abcdefghijklmnz]/z/g'

sed그 일을 수행하다콘텐츠줄 바꿈이 자동으로 유지됩니다.

관련 정보