grep 출력을 짧은 라인으로 제한


8

나는 종종 grep을 사용하여 다음과 같은 특정 항목을 가진 파일을 찾습니다.

grep -R 'MyClassName'

좋은 점은 파일과 그 내용을 반환하고 찾은 문자열을 빨간색으로 표시한다는 것입니다. 나쁜 점은 전체 텍스트가 하나의 큰 한 줄로 작성된 큰 파일도 있다는 것입니다. 이제 큰 파일 내에서 텍스트를 찾을 때 grep 출력이 너무 많습니다. 출력을 예를 들어 왼쪽과 오른쪽으로 5 단어로 제한하는 방법이 있습니까? 또는 왼쪽과 오른쪽으로 출력을 30 자로 제한합니까?


3
파이프 결과 통해cut
Rinzwind

당신이 찾고있는 패턴이 50 번 위치에 있지만 30 글자 만 원한다고하자. 그러면 어떻게 하시겠습니까? 해당 라인을 무시하거나 출력에 포함 시키지만 다듬 으십시오. 정확히 검색을 제한하고 싶습니까?
Sergiy Kolodyazhnyy

1
@Rinzwind 나는 cut구분 기호 또는 문자 수로 만 나눠서 달성하고자하는 것을 이해하지 못합니다 . 내가 줄을 찾을 때 줄의 MyClassName어느 곳에 나있을 수는 있지만 항상 같은 위치에 있지는 않습니다. 또한 앞뒤에 문자가 변형되어 구분 기호로 나눌 가능성이 없습니다.
소크라테스

1
@SergiyKolodyazhnyy 양의 줄을 MyClassName찾았을 때 결과적으로 파일 이름과 x 문자를 왼쪽과 오른쪽으로 가져 오려고 합니다. x는 예를 들어 30과 같이 제공 한 임의의 숫자입니다. 나머지 파일 내용은 무시됩니다. 이는 일치하는 파일에 대한 컨텍스트를 가져오고 과부하를 제한하기위한 것입니다.
소크라테스

1
@Rinzwind 사용자 정의 구분 기호의 어떤 종류의 당신은에 제안 cut다음과 같은 입력과 세 개의 파일이있는 경우 : oiadfaosuoianavMyClassNameionaernaldfajd/(/&%%§%/(§(/MyClassName&((/$/$/(§/$&public class MyClassName { public static void main(String[] args) { } }?
소크라테스

답변:


15

grep그 자체에는 라인 기반 컨텍스트 옵션 만 있습니다. 이 SU 게시물에서 대안을 제안합니다 .

해결 방법은 'only-matching'옵션을 활성화 한 다음 RegExp의 힘을 사용하여 텍스트보다 조금 더 많이 grep하는 것입니다.

grep -o ".\{0,50\}WHAT_I_M_SEARCHING.\{0,50\}" ./filepath

물론 색상 강조 표시를 사용하는 경우 항상 실제 일치 항목 만 채색하도록 다시 grep 할 수 있습니다.

grep -o ".\{0,50\}WHAT_I_M_SEARCHING.\{0,50\}"  ./filepath | grep "WHAT_I_M_SEARCHING"

또 다른 대안으로 fold텍스트를 입력 한 다음 그 랩핑하는 것이 좋습니다 .

fold -sw 80 input.txt | grep ...

-s옵션을 사용 fold하면 단어 사이를 긋지 않고 다음 줄로 푸시 단어를 만듭니다 .

또는 다른 방법으로 입력 구조에 따라 입력을 줄로 나눕니다. (예를 들어 SU 게시물은 JSON을 다루었으므로 etc를 사용 jq하여 예쁘게 인쇄하고 grep... 또는 jq자체적으로 필터링을 수행하는 것이 위에 주어진 두 가지 대안 중 하나보다 낫습니다.)


이 GNU awk 방법은 더 빠를 수 있습니다.

gawk -v n=50 -v RS='MyClassName' '
  FNR > 1 { printf "%s: %s\n",FILENAME, p prt substr($0, 0, n)}
  {p = substr($0, length - n); prt = RT}
' input.txt
  • 우리가 (관심있는 패턴에 분할 레코드 AWK에게 -v RS=...(), 문맥의 문자 수 -v n=...)
  • 첫 번째 레코드 ( FNR > 1) 뒤의 각 레코드 는 awk가 패턴과 일치하는 레코드 입니다.
  • 우리는 인쇄 그래서 n이전 행 (의 문자 후행 p)과 n현재 라인 (에서 선두 문자 substr($0, 0, n)(인 이전 행에 대한 일치하는 텍스트와 함께) prt)
    • 우리는 설정 p하고 인쇄 prt 한 후 다음 줄 에서 설정 한 값을 사용합니다.
    • RT GNUism입니다. 이것이 GNU awk에 특정한 이유입니다.

재귀 적 검색의 경우 :

find . -type f -exec gawk -v n=50 -v RS='MyClassName' 'FNR>1{printf "%s: %s\n",FILENAME, p prt substr($0, 0, n)} {p = substr($0, length-n); prt = RT}' {} +

2
좋아, 작동합니다. Regex가 유효한 접근법 인 것 같습니다. 처리 시간은 꽤 큽니다. 위의 게시물과 같이 Regex가 없으면 4.912가 걸리고 게시물과 같이 Regex가 있으면 3m39.312s가 걸립니다.
소크라테스

1
@Socrates는 위에서 추가 한 awk 방법이 더 잘 수행되는지 확인합니다
muru

1
fold검색된 문자열이 테두리에 나타나지 않는 경우에만 이 방법을 사용할 수 있습니다. 그렇지 않으면에 의해 숨겨집니다 grep.
Melebius

1
@muru 제안 해 주셔서 감사합니다 gawk. 불행히도 find내 시스템에서 실행될 때 제안 된 명령은 임의의 항목 을 출력하고 파일 이름 을 출력하지 않습니다. 또한, 나는 awk명령을 올바르게 분석 하기에 충분히 유창하지 않습니다 . 현재 Regex와 함께 사용 grep하면 문제는 빠르지 않지만 신뢰할 수 있습니다. 다시 한번 감사드립니다.
소크라테스

1
@ Socrates 나는 awk 명령을 수정했다고 생각합니다. 내 정신 모델은 어떤 줄 RT과 접두사 등을 사용 해야할지 잘못 되었습니다.
muru

1

사용 에만 일치를 다른 대답에 언급 된 정규식의 프로세싱 오버 헤드없이, 아주 가까이 당신이 찾고있는 무엇을 할, (아래 참조) 다른 옵션과 함께 수

grep -RnHo 'MyClassName'
  • n 숫자 출력, 일치하는 줄 번호 표시
  • H 파일 이름, 일치하는 줄의 시작 부분에 파일 이름을 표시하십시오.
  • o 일치 만하고, 전체 줄이 아니라 계산 된 문자열 만 표시

결과가 훨씬 빨리 발견되는 것은 사실이지만 정보가 누락되었습니다. 파일 경로가 표시되고 줄 번호가 표시되지만 텍스트 출력은 초기 검색 일뿐 MyClassName입니다. 따라서 컨텍스트가 없습니다.
소크라테스

grep -RnHo "MyClassName"grep -Rno "MyClassName"같은 출력을 갖는다.
소크라테스

@Socrates 출력은 같은 디렉토리에 H 가 없으면 동일하지 않습니다
Robert Riedl

-o정규식은 약간의 변수 부분이 있다면 플래그는 재미있을 수 있습니다. 고정 문자열의 경우 매번 인쇄하는 것이 쓸모가 없습니다. OP는 가까운 맥락에 관심이있을 가능성이 높습니다.
Melebius

1
@ Socrates, 진정한 맥락이 빠져 있지만 그 점이 핵심이라고 생각 했습니까? 출력을 제한합니까? 앞에 ( -B 1) 또는 뒤에 ( -A 1) 줄을 추가하여 컨텍스트를 다시 추가 할 수 있습니다 . 더 도움을 줄 수 없어서 죄송합니다.
Robert Riedl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.