![ls -a를 사용한 grep 명령이 작동하지 않습니까?](https://linux55.com/image/96068/ls%20-a%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%9C%20grep%20%EB%AA%85%EB%A0%B9%EC%9D%B4%20%EC%9E%91%EB%8F%99%ED%95%98%EC%A7%80%20%EC%95%8A%EC%8A%B5%EB%8B%88%EA%B9%8C%3F.png)
내 홈 디렉토리에 있는 일부 숨겨진 파일을 나열하려고 하는데 grep
명령과 결합하면 매우 이상한 명령 동작이 발생합니다 ls
.
ls -a
내 홈 디렉터리에서 실행했고 숨겨진 파일을 포함하여 예상한 대로 모든 파일을 얻었습니다 .- 모두 나열하고 싶어요숨겨진 파일"xau"로 시작해서 실행해봤는데
ls -a |grep -i .xau*
역시 예상대로 작동하더군요. - 그런 다음
ls -a |grep -i .x*
동일한 디렉토리에서 실행하지만전혀 아무것도 나열되어 있지 않습니다. - 그럼 내가 실수로 입력한 거야
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'가 옵니다"가 포함되어 있습니다. :)
요약:
원하는 결과를 얻으려면 다음 두 가지를 알아야 합니다.
- 따옴표가 없는 특수 전역 문자( 및
*
기타 일부 문자 포함)가 확장됩니다.?
[]
쉘을 통해명령을 실행하기 전에보다그들과 - 정규식은 파일 글로브와 다르며 더 강력합니다.
답변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