하나의 명령줄 문에 Grep 2개의 서로 다른 요구 사항이 있습니다.

하나의 명령줄 문에 Grep 2개의 서로 다른 요구 사항이 있습니다.

이 문자열을 포함하는 마지막 3줄을 인쇄하는 방법 #includetester.c이 문자열을 포함하는 줄이 3줄 미만인 경우 인쇄합니다.전체 파일.

지금까지 나는 다음을 가지고 있습니다 :

grep "#include" tester.c | tail -3

그런데 요구사항의 후반부를 어떻게 포함해야 할지 모르겠습니다. 이건 숙제이고 답은 한 줄이어야 하는데, 아니 ;그래서 도저히 알 수가 없는 것 같아요.

답변1

tail -33줄 이상을 인쇄하지 않고 3줄 이하로 인쇄합니다. 따라서 'grep'이 3개 이하의 일치하는 행을 찾으면 tail은 이를 모두 표준 출력으로 전달합니다. 일치하는 항목이 3개 이상인 경우 tail3개 행으로만 제한하세요.

귀하의 명령이 정확히 필요한 것이기 때문에 여기에 게시하기도 전에 문제를 해결하셨습니다.

밤에 일하면 이런 일이 벌어집니다 :)

편집: 귀하의 질문을 잘못 읽었을 수도 있습니다.

일치하는 항목이 3개 미만일 때 전체 파일을 인쇄하려면 다음을 실행하세요.

f="testfile.c" && C=3 && [ $(grep -c "#include" ${f}) -lt ${C} ] && cat ${f} || grep "#include" ${f} |tail -${C}

그러나 잠재적으로 느린 FS(예: NFS)를 처리하거나 줄 수가 많거나 매우 긴 줄이 있는 파일을 처리하는 경우에는 읽어야 하므로 너무 느릴 수 있습니다. 파일을 두 번 .

f="testfile.c" && C=3 && CONTENT=$(cat "${f}") && MATCHES=$(echo "$CONTENT"|grep "#include"|tail -${C}) && [ $(echo "$MATCHES" | wc -l) -lt ${C} ] && echo "$CONTENT" || echo "$MATCHES"

이렇게 하면 파일을 한 번만 열고 읽을 수 있지만 RAM(저장 장치보다 훨씬 빠릅니다)에 버퍼링하게 됩니다. RAM이 부족하거나 파일을 버퍼링하는 데 비용이 너무 많이 드는 경우 [파일을 두 번 여는 경우] 첫 번째 명령을 사용하면 속도가 느려지지만 OS나 응용 프로그램이 중단되지는 않습니다. "D" 상태에 갇힌 경우가 더 높습니다... OS에도 좋지 않습니다...)

답변2

다음과 같이 ";" 없이 Sildoreth가 말한 대로 할 수 있습니다.

test $(echo `grep "#include" tester.c` | wc -l) -ge 3 && {echo `grep "#include" tester.c` | head -n 3} || cat tester.c

답변3

특히 원래 게시물에서 요청한 명령이 정확히 원하는 명령이라는 점을 고려하면 이것은 이상한 질문입니다.

예를 들어 file.c에는 grep 표현식과 일치하는 15개 줄이 있습니다.

% grep -c "#include" file.c 15 % grep "#include" file.c | head -18 #(more than the number of matches) #include <sys/blah.h> #include <sys/blah2.h> #include <sys/blah3.h> #include <sys/blah4.h> #include <sys/blah5.h> #include <sys/blah6.h> #include <sys/blah7.h> #include <sys/blah8.h> #include <sys/blah9.h> #include <sys/blah10.h> #include <sys/blah11.h> #include <sys/blah12.h> #include <sys/blah13.h> #include <sys/blah14.h> #include <sys/blah15.h>

또는

% grep "#include" file.c | tail -18 #include <sys/blah.h> #include <sys/blah2.h> #include <sys/blah3.h> #include <sys/blah4.h> #include <sys/blah5.h> #include <sys/blah6.h> #include <sys/blah7.h> #include <sys/blah8.h> #include <sys/blah9.h> #include <sys/blah10.h> #include <sys/blah11.h> #include <sys/blah12.h> #include <sys/blah13.h> #include <sys/blah14.h> #include <sys/blah15.h>

이것이 귀하의 업무 매개변수에 맞지 않는 이유를 설명해 주세요.

답변4

이 시도:

lines=$(grep "#include" tester.c);
   test $(echo $lines | wc -l) -ge 3 && {echo $lines | head -n 3} || cat tester.c;
       unset lines

참고: 이 솔루션은 한 줄에 입력할 수 있습니다. 읽기 쉽도록 여러 줄로 나누었습니다.

편집하다

의견에 대한 응답으로 세미콜론을 &&다음으로 바꿀 수 있다고 생각합니다.

lines=$(grep "#include" tester.c) &&
   test $(echo $lines | wc -l) -ge 3 && {echo $lines | head -n 3} || cat tester.c

기술적으로 문제는 없지만 lines해결되었습니다. 이것도 &&불필요하지만 괜찮습니다.

이 수정된 솔루션은 다른 솔루션처럼 파일을 두 번 읽을 필요가 없다는 장점이 있습니다.

그렇게 할 수 없으면 test다음과 같이 괄호를 사용할 수 있습니다.

lines=$(grep "#include" tester.c) &&
   [ $(echo $lines | wc -l) -ge 3 ] && {echo $lines | head -n 3} || cat tester.c

중괄호를 제거할 수도 있습니다.

lines=$(grep "#include" tester.c) &&
   [ $(echo $lines | wc -l) -ge 3 ] && echo $lines | head -n 3 || cat tester.c

이러한 변형 중 하나가 요구 사항을 충족해야 합니다.

관련 정보