ls -a를 사용한 grep 명령이 작동하지 않습니까?

ls -a를 사용한 grep 명령이 작동하지 않습니까?

내 홈 디렉토리에 있는 일부 숨겨진 파일을 나열하려고 하는데 grep명령과 결합하면 매우 이상한 명령 동작이 발생합니다 ls.

  1. ls -a내 홈 디렉터리에서 실행했고 숨겨진 파일을 포함하여 예상한 대로 모든 파일을 얻었습니다 .
  2. 모두 나열하고 싶어요숨겨진 파일"xau"로 시작해서 실행해봤는데 ls -a |grep -i .xau*역시 예상대로 작동하더군요.
  3. 그런 다음 ls -a |grep -i .x*동일한 디렉토리에서 실행하지만전혀 아무것도 나열되어 있지 않습니다.
  4. 그럼 내가 실수로 입력한 거야ls -a |grep -i .*x (이번에는 와일드카드 문자 *와 문자 'x'가 자리를 바꿨습니다.)흥미롭게도 3단계에서 예상한 대로 작동합니다. 이 명령 으로 같은 것을 시도 ls -a .*x했지만ls -a .*X해당 파일이나 디렉터리가 없습니다.실수.

여기에 이미지 설명을 입력하세요.

여기에 이미지 설명을 입력하세요.

실제 텍스트 출력을 추가했습니다.여기.

왜 직접 사용하지 않느냐고 하시는 분들도 계시겠지만, ls -a .x*적절한 grep색상이 출력됩니다. 그럼 누군가 나에게 이것을 설명해 줄 수 있습니까?

답변1

당신은 고통 받고 있습니다조기 글로벌 확장.

.xa*현재 디렉터리의 어떤 항목과도 ​​일치하지 않으므로 확장되지 않습니다. (Glob은 대소문자를 구분합니다.) 그러나.x* 하다특정 파일과 일치하므로 쉘은 grep파일을 보기 전에 해당 파일을 확장합니다.

여러 인수를 받으면 grep첫 번째 인수가 패턴이고 나머지 인수는 해당 패턴을 검색할 파일이라고 가정합니다.

따라서 명령에서 ls -a | grep -i .x*출력은 다음과 ls같습니다.무시당하다, ".xsession-errors" 패턴에 대해 ".xsession-errors.old" 파일을 검색합니다. 당연히 아무것도 발견되지 않았습니다.

이를 방지하려면 작은따옴표나 큰따옴표로 특수 문자를 묶으십시오. 예를 들어:

ls -a | grep -i '.x*'

당신도 고통받고 있어요정규식과 glob 사이의 혼란.

리터럴 문자열 ".x"로 시작하고 그 뒤에 아무 것도 오는 파일을 찾는 것 같지만 정규식은 파일 와일드카드와 같은 방식으로 작동하지 않습니다. 이것* 정규식으로파일 glob에서와 같이 "문자의 순서"가 아니라 "0개 이상의 선행 문자"를 의미합니다. 당신은 어때요?아마도당신이 원하는 것은 :

ls -a | grep -i '^\.x'

이름이 다음과 같은 파일을 검색합니다.시작리터럴 문자 ".x" 또는 ".X"를 사용합니다. 실제로 문자만 지정하기 때문에 대신 문자 클래스를 쉽게 사용할 수 있습니다 -i.

ls -a | grep '^\.[xX]'

요점은정규식은 파일 글로브와 매우 다릅니다.

제안된 대로 시도해 보면 ls -a | grep -i '.x*'모든 파일이 표시된다는 사실에 매우 놀라게 될 것입니다! (직접 출력과 동일하며 ls -a에서와 같이 별도의 줄에 있습니다 ls -a -1.)

어떻게요?

글쎄요정규식(그러나 쉘 글로브에서는 아님) 마침표( .)는 "모든 단일 문자"를 의미합니다. 별표( *)는 "0개 이상의 선행 문자"를 의미합니다. 따라서 정규식은 .x*"'x' 문자의 인스턴스가 0개 이상 뒤에 오는 모든 문자"를 의미합니다.

물론 파일 이름이 비어 있으면 안 됩니다.모든파일 이름에는 "문자 뒤에 최소한 0개의 'x'가 옵니다"가 포함되어 있습니다. :)


요약:

원하는 결과를 얻으려면 다음 두 가지를 알아야 합니다.

  1. 따옴표가 없는 특수 전역 문자( 및 *기타 일부 문자 포함)가 확장됩니다.?[]쉘을 통해명령을 실행하기 전에보다그들과
  2. 정규식은 파일 글로브와 다르며 더 강력합니다.

답변2

문제는 *주위에 따옴표를 넣지 않고 명령을 실행하기 전에 쉘이 확장하도록 한다는 것입니다. 바라보다:

$ touch .xau1 .xau2
# this won't work
$ ls -a | grep -i .xau*
# but this does
$ ls -a | grep -i ".xau*"
.xau1
.xau2
# this one too
$ ls -a | grep -i '.xau*'
.xau1
.xau2
# check what shell sees
$ ls -a | grep -i .xau* # now don't press enter but C-x * and you'll see this:
$ ls -a | grep -i .xau1 .xau2

관련 정보