쉘(예: bash)은 와일드카드 패턴을 어떻게 확장합니까?

쉘(예: bash)은 와일드카드 패턴을 어떻게 확장합니까?

디렉토리에 문자 "a"로 시작하는 100개의 파일이 있다고 가정합니다.

grep <some string> a*터미널에서 실행 하면 쉘이 이를 어떻게 처리합니까?

정규식을 확장하고 a로 시작하는 모든 파일 목록을 가져오고 각 파일을 순서대로 grep합니까? 아니면 다른 방법이 있나요?

위의 "a"로 시작하는 파일 이름 배열이 있다고 가정해 보겠습니다. for 루프를 작성하고 쉘 스크립트나 ac 프로그램에서 직접 반복을 수행하면 시간이 더 걸리거나 덜 걸리나요?

답변1

a*첫째, 약간의 문제입니다. 일반적인 쉘 구문과 같은 문자열은 정규식과 다르게 작동하는 glob입니다.

일반적으로 쉘 인터프리터(예: bash)는 문자열을 a*패턴과 일치하는 각 파일 이름 목록으로 확장합니다 a*. 그러면 이는 명령줄 인수의 일부가 됩니다.하나의( 프로그래머 의 경우 grep모든 확장 단어는 별도의 문자열 인수로 제공됩니다 argv) main. 그런 다음 명령은 grep선택한 방식으로 인수를 구문 분석하고 grep이를 파일 이름, 옵션, 옵션 매개변수, 정규식 등으로 해석하고 적절한 조치를 취합니다. 모든 것은 순차적으로 발생합니다(내가 아는 한 다중 스레드를 사용한 구현은 없습니다 grep).

동일한 작업을 수행하기 위해 쉘 스크립트에서 루프를 구현한 경우 다음과 같은 이유로 위 프로세스보다 속도가 거의 느려질 것입니다. 각 파일에 대해 새로운 grep 프로세스를 생성하면 불필요한 프로세스 생성 오버헤드로 인해 속도가 확실히 느려집니다. 쉘 스크립트에서 직접 인수 목록을 작성하고 단일 인스턴스를 사용하는 경우 grep쉘 명령이 (bash를 통해) 해석되어야 하고 추가 코드 레이어가 추가되므로 쉘에서 수행하는 모든 작업은 여전히 ​​느려질 것입니다. 그리고 컴파일된 코드에서 bash가 내부적으로 더 빠르게 수행하는 작업을 다시 구현하면 됩니다.

C로 직접 작성하는 경우 첫 번째 단락에 설명된 프로세스와 비슷한 성능을 쉽게 얻을 수 있지만 특정 최적화를 탐구하지 않고는 시간을 정당화할 만큼 현재 grep/bash 구현에 비해 충분한 성능 향상을 얻을 가능성이 낮습니다. 기계 성능이 아니면 이식성이 희생됩니다. 어쩌면 임의로 병렬화할 수 있는 버전을 만들려고 시도할 수도 있지만 grepCPU 바인딩보다 I/O 바인딩에 더 많이 의존하기 때문에 그것도 도움이 되지 않을 수 있습니다. 전역 확장과 grep은 대부분의 "일반적인" 용도에 "충분히 빠릅니다".

답변2

예, 파일 목록으로 확장되어 결과 목록을 프로그램에 제공합니다 grep. 적어도 그것은 man bash하위 섹션에서 말한 것 입니다.경로명 확장.

grep <some_string> a언급했듯이 간단한 경우에 확장을 사용하는 또 다른 방법 이 있습니다.누르기 전에*, 에 따르면 ESC. 그러면 명령줄에서 일치하는 파일 목록이 확장되므로 를 누르기 전에 목록이 올바른지 확인할 수 있습니다 Enter.

질문의 두 번째 부분은 상황에 따라 다릅니다. 각 파일에 대해 차례로 grep을 실행하는 for 루프를 작성한다면 grep 프로그램이 한 번 실행되지 않고 각 파일에 대해 한 번 실행되기 때문에 확실히 속도가 느려질 것입니다. 그러나 무엇특정 사항이 있다는 것을 기억하는 것이 중요합니다.한계명령줄 인수의 확장된 길이를 사용할 수 있지만 일반적으로 꽤 깁니다. 이것을 보려면 시도해 볼 수 있습니다 grep adasdsadf /usr/*/*/* >/dev/null.

관련 정보