개발자를 위한 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/ 디렉터리의 파일을 자세히 살펴보고 싶습니다.

nashornNashorn(또는 다른 참조)에 대한 참조를 모두 찾아야 하므로 여기서는 대소문자를 구분하지 않는 검색(-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 명령의 기능을 이해하고 이를 도구 상자에 추가하는 데 도움이 되기를 바랍니다. 틀림없이 후회하지 않으실 겁니다!