개발자를 위한 10가지 실용적인 Grep 명령 예
grep 명령은 파일에서 패턴을 찾는 데 사용됩니다. 이 튜토리얼에서는 소프트웨어 개발자에게 특히 도움이 되는 가장 일반적인 grep 명령 예제 중 일부를 보여줍니다.
최근에 저는 Asciidoctor.js를 사용하고 Asciidoctor.js-pug 및 Asciidoctor-templates 작업을 시작했습니다. js 프로젝트.
수천 줄이 포함된 코드베이스를 처음으로 파고들 때 즉시 효과를 발휘하는 것이 항상 쉬운 것은 아닙니다. 하지만 수많은 코드 라인을 헤쳐나가는 나의 비밀 무기는 grep
도구입니다.
Linux에서 grep 명령을 사용하는 방법을 예제와 함께 공유하겠습니다.
Linux에서 grep 명령의 실제 유용한 예
man
을 살펴보면 grep
도구에 대한 간단한 설명을 볼 수 있습니다: “패턴과 일치하는 줄을 인쇄합니다. ”
그러나 그런 허술한 정의에 속지 마십시오. grep
은 Unix 도구 상자에서 가장 유용한 도구 중 하나이며 텍스트 파일 작업을 하자마자 이를 사용할 경우가 무수히 많습니다.
실제 사례를 통해 사물이 어떻게 작동하는지 배우는 것이 항상 더 좋습니다. 따라서 Asciidoctor.js 소스 트리를 사용하여 grep
기능 중 일부를 설명하겠습니다.
GitHub에서 해당 소스 트리를 다운로드할 수 있으며, 원한다면 이 기사를 작성할 때 사용한 것과 동일한 변경 세트를 확인할 수도 있습니다. 그러면 이 문서의 나머지 부분에 설명된 것과 완벽하게 동일한 결과를 얻을 수 있습니다.
git clone https://github.com/asciidoctor/asciidoctor.js
cd asciidoctor.js
git checkout v1.5.6-rc.1
1. 문자열의 모든 항목 찾기(기본 사용법)
Asciidoctor.js는 Java 플랫폼용 Nashorn JavaScript 엔진을 지원합니다. 나는 Nashorn을 알지 못하므로 해당 JavaScript 엔진을 참조하는 프로젝트 부분을 탐색하여 Nashorn에 대해 더 자세히 배울 수 있는 기회를 가질 수 있었습니다.
시작점으로 프로젝트 종속성을 설명하는 package.json
파일에 Nashorn과 관련된 일부 설정이 있는지 확인했습니다.
linux@handbook:~$ grep nashorn package.json
"test": "node npm/test/builder.js && node npm/test/unsupported-features.js && node npm/test/jasmine-browser.js && node npm/test/jasmine-browser-min.js && node npm/test/jasmine-node.js && node npm/test/jasmine-webpack.js && npm run test:karmaBrowserify && npm run test:karmaRequirejs && node npm/test/nashorn.js",
예, Nashorn 관련 테스트가 있었던 것 같습니다. 그럼 조금 더 조사해 보겠습니다.
2. 파일 세트에서 대소문자를 구분하지 않는 검색
이제 Nashorn을 명시적으로 언급하는 ./npm/test/
디렉터리의 파일을 자세히 살펴보고 싶습니다.
nashorn
및 Nashorn
(또는 다른 참조)에 대한 참조를 모두 찾아야 하므로 여기서는 대소문자를 구분하지 않는 검색(-i
옵션)이 더 나을 것입니다. 대문자와 소문자 조합):
linux@handbook:~$ grep -i nashorn npm/test/*.js
npm/test/nashorn.js:const nashornModule = require('../module/nashorn');
npm/test/nashorn.js:log.task('Nashorn');
npm/test/nashorn.js:nashornModule.nashornRun('jdk1.8.0');
실제로 여기서는 대소문자를 구분하지 않는 것이 유용했습니다. 그렇지 않았다면 require('../module/nashorn')
문을 놓쳤을 것입니다. 의심할 바 없이 나중에 해당 파일을 더 자세히 조사해야 할 것입니다.
3. 일치하지 않는 모든 파일 찾기
그런데 npm/test/
디렉토리에 Nashorm이 아닌 특정 파일이 있습니까? 이 질문에 답하기 위해 grep의 "일치하지 않는 파일 인쇄" 옵션(-L
옵션)을 사용할 수 있습니다.
sh$ grep -iL nashorn npm/test/*
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js
-L
옵션을 사용하면 grep
의 출력이 파일 이름만 표시하도록 어떻게 변경되었는지 확인하세요. 따라서 위의 파일 중 어떤 파일에도 "nashorn"이라는 문자열이 포함되어 있지 않습니다(경우에 관계없이). 그렇다고 그 기술과 관련이 없다는 뜻은 아니지만, 적어도 "n-a-s-h-o-r-n"이라는 글자는 존재하지 않습니다.
4. 숨겨진 파일과 하위 디렉터리에서 반복적으로 패턴 찾기
마지막 두 명령은 쉘 glob 패턴을 사용하여 검사할 파일 목록을 grep
명령에 전달했습니다.
그러나 여기에는 몇 가지 고유한 제한 사항이 있습니다. 별표(*
)는 숨겨진 파일과 일치하지 않습니다. 또한 하위 디렉터리에 포함된 파일(결국)과도 일치하지 않습니다.
해결책은 쉘 glob 패턴에 의존하는 대신 grep
을 find 명령과 결합하는 것입니다.
# This is not efficient as it will spawn a new grep process for each file
linux@handbook:~$ find npm/test/ -type f -exec grep -iL nashorn \{} \;
# This may have issues with filenames containing space-like characters
linux@handbook:~$ grep -iL nashorn $(find npm/test/ -type f)
위 코드 블록의 주석에서 언급했듯이 각 솔루션에는 단점이 있습니다.
공백과 같은 문자가 포함된 파일 이름과 관련하여 find
명령의 -print0
옵션과 결합된 grep -z
옵션을 조사해 보겠습니다. , 해당 문제를 완화할 수 있습니다. 주저하지 말고 이 기사 끝에 있는 댓글 섹션을 사용하여 해당 주제에 대한 아이디어를 공유하세요!
그럼에도 불구하고 더 나은 솔루션은 grep의 "재귀적" 옵션을 사용하는 것입니다. 이 옵션을 사용하면 검사할 파일 이름의 명시적 목록 대신 검색 트리의 루트(시작 디렉터리)를 명령줄에 제공할 수 있습니다.
-r
옵션을 사용하면 grep은 숨겨진 파일을 포함하여 지정된 디렉터리의 모든 파일을 검색한 다음 재귀적으로 하위 디렉터리로 내려갑니다.
linux@handbook:~$ grep -irL nashorn npm/test/npm/
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js
실제로 해당 옵션을 사용하면 한 수준 위에서 탐색을 시작하여 Nashorn을 대상으로 하는 비 npm 테스트도 있는지 확인할 수도 있습니다.
linux@handbook:~$ grep -irL nashorn npm/
그 명령을 직접 테스트하여 결과를 확인하도록 하겠습니다. 하지만 힌트로, 일치하는 파일을 더 많이 찾아야 한다고 말할 수 있습니다!
5. 이름으로 파일 필터링(정규식 사용)
따라서 해당 프로젝트에는 Nashorn 관련 테스트가 있는 것 같습니다. Nashorn은 Java이므로 제기될 수 있는 또 다른 질문은 “프로젝트에 Nashorn을 명시적으로 언급하는 일부 Java 소스 파일이 있습니까?”입니다. ”.
사용하는 grep
버전에 따라 해당 질문에 답할 수 있는 해결책이 최소한 두 가지 있습니다.
첫 번째는 grep
를 사용하여 "nashorn" 패턴이 포함된 모든 파일을 찾은 다음 첫 번째 명령의 출력을 Java가 아닌 항목을 필터링하는 두 번째 grep
인스턴스로 파이프하는 것입니다. 소스 파일:
linux@handbook:~$ grep -ir nashorn ./ | grep "^[^:]*\.java"
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/basic.js"));
이제 명령의 전반부를 이해할 수 있을 것입니다. 하지만 “^[\^:]*\\.java” 부분은 어떻습니까?
-F
옵션을 지정하지 않으면 grep
는 검색 패턴이 정규식이라고 가정합니다. 즉, 축어적으로 일치하는 일반 문자 외에도 더 복잡한 패턴을 설명하기 위한 메타 문자 세트에 액세스할 수 있습니다. 위에서 사용한 패턴은 다음과만 일치합니다.
^
줄의 시작[^:]*
뒤에 콜론을 제외한 모든 문자 시퀀스\.
뒤에 점이 표시됩니다. (점은 regex에서 특별한 의미를 가지므로 원하는 것을 표현하기 위해 백슬래시로 보호해야 했습니다. 문자 그대로 일치)java
뒤에 네 글자 “java. ”
실제로 grep
는 콜론을 사용하여 파일 이름을 컨텍스트에서 분리하므로 파일 이름 섹션에 .java
가 있는 줄만 유지합니다. 언급할 가치가 있는 것은 .javascript
파일 이름과도 일치한다는 것입니다. 원하시면 직접 해결해 보도록 하겠습니다.
6. grep을 사용하여 이름으로 파일 필터링
정규식은 매우 강력합니다. 그러나 특별한 경우에는 과잉인 것 같습니다. 위의 솔루션에 대해서는 언급하지 않고 "nashorn" 패턴을 검색하기 위해 모든 파일을 검사하는 데 시간을 소비합니다. 대부분의 결과는 파이프라인의 두 번째 단계에서 삭제됩니다.
Linux를 사용하는 경우와 같이 grep
의 GNU 버전을 사용하는 경우 --include
옵션을 사용하면 다른 해결 방법이 있습니다. 이는 이름이 주어진 glob 패턴과 일치하는 파일만 검색하도록 grep
에 지시합니다.
linux@handbook:~$ grep -ir nashorn ./ --include='*.java'
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java: ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java: engine.eval(new FileReader("./spec/nashorn/basic.js"));
7. 단어 찾기
Asciidoctor.js 프로젝트의 흥미로운 점은 다중 언어 프로젝트라는 것입니다. 핵심적으로 Asciidoctor는 Ruby로 작성되었으므로 JavaScript 세계에서 사용하려면 Ruby에서 JavaScript 소스-소스 컴파일러인 Opal을 사용하여 "트랜스파일"해야 합니다. 이전에 몰랐던 또 다른 기술.
그래서 Nashorn의 특성을 조사한 후 Opal API를 더 잘 이해하는 작업을 나 자신에게 할당했습니다. 그 탐구의 첫 번째 단계로 저는 프로젝트의 JavaScript 파일에서 Opal
전역 개체에 대한 언급을 모두 검색했습니다. 이는 가식(Opal =
), 회원 액세스(Opal.
) 또는 다른 맥락에서도 나타날 수 있습니다. 정규식이 트릭을 수행할 것입니다. 그러나 grep
에는 이러한 일반적인 사용 사례를 해결할 수 있는 좀 더 가벼운 솔루션이 있습니다. -w
옵션을 사용하면 단어, 즉 앞뒤에 단어가 아닌 문자가 오는 패턴만 일치합니다. 단어가 아닌 문자는 줄의 시작, 줄의 끝 또는 문자, 숫자, 밑줄이 아닌 모든 문자입니다.
linux@handbook:~$ grep -irw --include='*.js' Opal .
...
8. 출력물 색칠하기
일치하는 항목이 많기 때문에 이전 명령의 출력을 복사하지 않았습니다. 출력이 이렇게 촘촘하면 이해하기 쉽도록 약간의 색상을 추가하는 것이 좋습니다. 이것이 시스템에 기본적으로 구성되어 있지 않은 경우 GNU --color
옵션을 사용하여 해당 기능을 활성화할 수 있습니다:
linux@handbook:~$ grep -irw --color=auto --include='*.js' Opal .
...
이전과 동일한 긴 결과를 얻어야 하지만 이번에는 검색 문자열이 아직 색상이 아닌 경우 색상으로 표시되어야 합니다.
9. 일치하는 줄 또는 일치하는 파일 계산
이전 명령의 출력이 매우 길다는 점을 두 번 언급했습니다. 정확히 얼마나 걸리나요?
linux@handbook:~$ grep -irw --include='*.js' Opal . | wc -l
86
이는 검사된 파일의 모든에 총 86개의 일치하는 줄이 있음을 의미합니다. 그러나 일치하는 파일은 몇 개입니까? -l
옵션을 사용하면 일치하는 <을 표시하는 대신 파일과 일치하는 grep
출력을 제한할 수 있습니다.라인. 따라서 간단한 변경을 통해 일치하는 파일 수를 알 수 있습니다.
linux@handbook:~$ grep -irwl --include='*.js' Opal . | wc -l
20
-L
옵션이 생각난다면 놀랄 일이 아닙니다. 상대적으로 일반적이므로 소문자/대문자가 보완 옵션을 구별하는 데 사용됩니다. -l
은 일치하는 파일 이름을 표시합니다. -L
은 일치하지 않는 파일 이름을 표시합니다. 또 다른 예를 보려면 -h
/-H
옵션에 대한 설명서를 확인하세요.
괄호를 닫고 결과로 돌아가 보겠습니다. 86개의 일치하는 줄입니다. 일치하는 파일 20개. 그러나 일치하는 파일에서 일치하는 라인은 어떻게 배포됩니까? grep
의 -c
옵션을 사용하여 검사된 파일(일치 항목이 없는 파일 포함)당 일치하는 줄 수를 계산한다는 것을 알 수 있습니다.
linux@handbook:~$ grep -irwc --include='*.js' Opal .
...
종종 해당 출력은 파일을 검사한 순서대로 결과를 표시하고 일치하지 않는 파일도 포함하므로 약간의 후처리가 필요한 경우가 많습니다. 이는 일반적으로 우리가 관심을 갖지 않는 것입니다. 후자는 해결하기가 매우 쉽습니다.
linux@handbook:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$'
주문에 관해서는 파이프라인 끝에 sort 명령을 추가할 수 있습니다.
linux@handbook:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$' | sort -t: -k2n
내가 사용한 옵션의 정확한 의미는 sort
명령 매뉴얼을 확인하도록 하겠습니다. 아래 댓글 섹션을 사용하여 결과를 공유하는 것을 잊지 마세요!
10. 두 매칭 세트의 차이점 찾기
기억하시면 몇 가지 명령어 전에 제가 단어 “Opal. ” 그러나 동일한 파일 세트에서 문자열 “Opal”이 모두 검색되면 약 20개 이상의 답변을 얻을 수 있습니다.
linux@handbook:~$ grep -irw --include='*.js' Opal . | wc -l
86
linux@handbook:~$ grep -ir --include='*.js' Opal . | wc -l
105
이 두 세트의 차이점을 찾는 것은 흥미로울 것입니다. 그렇다면 "opal"이라는 네 글자가 연속적으로 포함되어 있지만 이 네 글자가 전체 단어를 형성하지 않는 행은 무엇입니까?
그 질문에 답하기는 그리 쉽지 않습니다. 같은 줄에는 Opal이라는 단어와 이 네 글자를 포함하는 더 큰 단어가 둘 다 포함될 수 있기 때문입니다. 그러나 첫 번째 근사치로 해당 파이프라인을 사용할 수 있습니다.
linux@handbook:~$ grep -ir --include='*.js' Opal . | grep -ivw Opal
./npm/examples.js: const opalBuilder = OpalBuilder.create();
./npm/examples.js: opalBuilder.appendPaths('build/asciidoctor/lib');
./npm/examples.js: opalBuilder.appendPaths('lib');
...
분명히 다음 단계는 opalBuilder
개체를 조사하는 것이지만 그건 다른 날에 할 예정입니다.
마지막 단어
물론 grep
명령 몇 개만 실행하는 것만으로는 코드 아키텍처는 물론이고 프로젝트 구성도 이해할 수 없습니다!
그러나 새로운 코드베이스를 탐색할 때 벤치마크와 시작점을 식별하려면 해당 명령이 불가피하다는 것을 알았습니다.
따라서 이 기사가 grep
명령의 기능을 이해하고 이를 도구 상자에 추가하는 데 도움이 되기를 바랍니다. 틀림없이 후회하지 않으실 겁니다!