범위를 사용하는 tr의 이상한 동작

범위를 사용하는 tr의 이상한 동작

tr을 사용할 때 이상한 동작을 보이는 특정 서버가 있습니다. 다음은 작동 중인 서버의 예입니다.

-bash-3.2$ echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
1234567890
-bash-3.2$

이것은 나에게 완벽하게 이해됩니다.

그러나 이는 "특수" 서버에서 가져온 것입니다.

[root@host~]# echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
abcdefghijklmnpqrstuvwxyz1234567890

보시다시피 모든 소문자를 제거하면 실패합니다. 그러나 문자 "o"는 제거됩니다.

흥미로운 부분은 다음 두 가지 예인데, 나에게는 이해가 되지 않습니다.

[root@host~]# echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-n]
opqrstuvwxyz1234567890
[root@host~]# echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-o]
abcdefghijklmnpqrstuvwxyz1234567890
[root@host~]#

(마지막 예에서는 "o"가 제거되었습니다)

여기서 무슨 일이 일어나고 있는지 아는 사람 있나요? 내가 사용하고 있는 다른 Linux 상자에서는 이를 재현할 수 없습니다.

답변1

o현재 디렉토리에 다음과 같은 파일이 있습니다.

foo> ls
foo> echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
1234567890
foo> touch o
foo> echo "abcdefghijklmnopqrstuvwxyz1234567890"|tr -d [a-z]
abcdefghijklmnpqrstuvwxyz1234567890

[a-z]일치하는 항목이 발견되면 쉘은 문자열을 확장합니다.

이를 경로 이름 확장이라고 합니다.man bash

경로 이름 확장
단어 분리 후 bash는 -f 옵션이 설정되지 않은 한 문자 *, ? 및 [에 대해 각 단어를 검색합니다. ... (...)

bash가 확장을 수행합니다.

[...]는 포함된 문자 중 하나와 일치합니다.

답변2

뭐가 문제 야

쉘(bash)은 인수를 봅니다 [a-z]. 이것은 와일드카드 패턴입니다(전반적인 상황), 이는 모든 소문자와 일치합니다. 따라서 쉘은 이 패턴과 일치하는 파일 이름을 찾습니다. 세 가지 상황이 있습니다:

  • 현재 디렉터리에는 이름이 단일 소문자인 파일이 없습니다. 그런 다음 쉘은 와일드카드 패턴을 그대로 유지하고 tr매개변수 -d[a-z]. 이는 대부분의 컴퓨터에서 발생합니다.
  • 현재 디렉터리의 개별 파일 이름은 단일 소문자로 지정됩니다. 그런 다음 쉘은 패턴을 해당 파일 이름으로 확장하고 tr인수 -d와 파일 이름을 확인합니다. 이는 서버에서 발생하며 문자가 제거된 o것을 볼 수 있듯이 일치하는 파일이 호출됩니다 .tro
  • 현재 디렉터리에 있는 두 개 이상의 파일 이름이 단일 소문자로 구성되어 있습니다. 그런 다음 쉘은 파일 이름 목록과 일치하도록 패턴을 확장하고 tr세 개 이상의 인수 -d및 파일 이름을 확인합니다. tr그 뒤에 매개변수가 필요 하기 때문에 -d불평합니다.

당신은 무엇을 해야

명령 인수에 특수 문자가 있으면 이스케이프해야 합니다. 매개변수를 작은따옴표로 묶습니다 '…'(이것이 가장 쉬운 방법이며 다른 방법도 있습니다). 작은따옴표 내에서는 작은따옴표 자체를 제외한 모든 문자가 자신을 나타냅니다. 매개변수에 작은따옴표가 있는 경우그것을로 바꾸십시오'\''.

tr -d '[a-z]'

하지만 이는 여전히 의도한 바가 아닐 수도 있다는 점에 유의하세요! tr소문자와 대괄호를 제거하라는 명령입니다 . 등에 해당합니다 tr -d ']a-z['. tr '[]a-z'소문자를 제거하려면 다음을 사용하십시오.

tr -d a-z

매개변수 tr는 문자 세트입니다. 정규식이나 와일드카드 패턴에서 괄호 안에 문자 세트를 넣어 해당 문자 세트가 문자 세트임을 나타낼 수 있습니다. 하지만 tr한 번에 한 캐릭터에만 적용됩니다. 명령줄 매개변수는 다음과 같습니다.괄호 안에 쓰는 내용.

표현하려면 괄호가 필요합니다.캐릭터 클래스. 정규 표현식에서는 괄호 안에 괄호를 사용하여 문자 클래스를 나타낼 수 있습니다. 예를 들어 [[:lower:]]*임의 개수의 소문자 일치, [[:lower:]_]*임의 개수의 소문자 및 밑줄 일치 등이 가능합니다. 인수에서 tr괄호 없이 세트를 원하므로 tr -d '[:lower:]'소문자 제거, tr -d '[:lower:]_'소문자 및 밑줄 제거 등을 수행합니다.

^ 일부 로케일에서는 다른 문자와 일치할 수 있습니다..

관련 정보