디렉토리에 문자 "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 구현에 비해 충분한 성능 향상을 얻을 가능성이 낮습니다. 기계 성능이 아니면 이식성이 희생됩니다. 어쩌면 임의로 병렬화할 수 있는 버전을 만들려고 시도할 수도 있지만 grep
CPU 바인딩보다 I/O 바인딩에 더 많이 의존하기 때문에 그것도 도움이 되지 않을 수 있습니다. 전역 확장과 grep은 대부분의 "일반적인" 용도에 "충분히 빠릅니다".
답변2
예, 파일 목록으로 확장되어 결과 목록을 프로그램에 제공합니다 grep
. 적어도 그것은 man bash
하위 섹션에서 말한 것 입니다.경로명 확장.
grep <some_string> a
언급했듯이 간단한 경우에 확장을 사용하는 또 다른 방법 이 있습니다.누르기 전에*
, 에 따르면 ESC. 그러면 명령줄에서 일치하는 파일 목록이 확장되므로 를 누르기 전에 목록이 올바른지 확인할 수 있습니다 Enter.
질문의 두 번째 부분은 상황에 따라 다릅니다. 각 파일에 대해 차례로 grep을 실행하는 for 루프를 작성한다면 grep 프로그램이 한 번 실행되지 않고 각 파일에 대해 한 번 실행되기 때문에 확실히 속도가 느려질 것입니다. 그러나 무엇예특정 사항이 있다는 것을 기억하는 것이 중요합니다.한계명령줄 인수의 확장된 길이를 사용할 수 있지만 일반적으로 꽤 깁니다. 이것을 보려면 시도해 볼 수 있습니다 grep adasdsadf /usr/*/*/* >/dev/null
.