grep은 경기 전후에 N 번째와 M 번째 라인을 반환합니다.


12

나는 GREP와 내가 필드를 사용할 수 있다는 것을 알고 -A와 -B경기에서 이전 및 다음 줄을 당깁니다.

그러나 그들은 많은 라인이 지정되어 있지만 일치하는 모든 라인을 가져옵니다.

grep -r -i -B 5 -A 5 "match" 

난 단지 5를 수신 할 일 경기 전에 라인과 5 번째 일치하는 라인에 추가 경기 후 라인 사이의 라인을 얻을 수 없습니다.

이 작업을 수행하는 방법이 grep있습니까?


1
당신은 그것을 sed에 배관함으로써 그것을 할 수 있습니다. 방금 이것을 테스트했는데 효과가 있었지만 파일에 정확히 1 개의 일치 항목이있을 때만 작동했습니다. grep -r -i -B 5 -A 5 "match" | sed -e 1b -e '$!d'
— Terrance

언급 한 것처럼 @Terrance는 감사합니다 .1000 줄을 수집하기 때문에 작동하지 않습니다.
— chollida

나는 grep 자체가 작동하지 않을 것이라고 생각합니다 ... 나는 당신을 위해 bash 스크립트를 작성하고 있습니다
— Joshua Besneatte

문제 없어요! 당신이 얻는 답변을 보는 데 관심이 있습니다. =)
— Terrance

이것은 하나의 파일 또는 여러 파일입니까?
— Joshua Besneatte

답변:


1

사용하려는 도구를 sift라고합니다. 이것은 기본적으로 스테로이드에 대한 grep입니다. 병행하십시오. Sift에는 원하는대로 정확하게 수행 할 수있는 다양한 옵션이 있습니다. 특히 특정 텍스트가 뒤에 오는 / 앞에 있지 않을 수있는 일치 항목과 관련하여 특정 줄을 반환합니다.

sift는 go 언어로 작성된 주류 gnu가 아니라 Linux에 잘 설치된다는 사실에 놀랍습니다. IT는 grep이 동일한 작업을 수행하는 데 몇 주가 걸리는 대량의 모든 텍스트를 사용하여 동시에 검색합니다.

Sift 웹 사이트-예제보기


AskUbuntu에 오신 것을 환영합니다. 답변 해 주셔서 감사합니다. sift 웹 사이트에 대한 링크를 제공하는 대신이 특정 문제를 해결할 수있는 CLI 예제를 제공해야합니다. 결국 Q & A입니다. 감사합니다.
— Bernard Wei

12

만약:

cat file
a
b
c
d
e
f match
g
h
i match
j
k
l
m
n
o

그때:

awk '
    {line[NR] = $0} 
    /match/ {matched[NR]} 
    END {
        for (nr in matched)
            for (n=nr-5; n<=nr+5; n+=5) 
                print line[n]
    }
' file
a
f match
k
d
i match
n

+1이지만 의미를 설명 할 수 /match/ {matched[NR]}있습니까? 배열이나 변수를 전체 명령으로 본 적이 없습니다. 일치하는 각 줄의 현재 레코드 번호를 배열에 넣습니까?
— Joe

할당이없는 배열 요소를 참조하면 해당 키가 값없이 배열에 추가됩니다. 그러면 해당 키가 표현식에 나타납니다 key in array. 내가하고있는 일은 패턴이 나타나는 줄 번호를 기억하는 것입니다
— glenn jackman

6

이것은 기본적으로 Glenn의 솔루션이지만 Bash, Grep 및 sed로 구현됩니다.

grep -n match file |
    while IFS=: read nr _; do
        sed -ns "$((nr-5))p; $((nr))p; $((nr+5))p" file
    done

행 번호가 1보다 작 으면 sed 오류가 발생하고 파일의 행 수보다 큰 행 번호는 아무 것도 인쇄하지 않습니다.

이것은 단지 최소한입니다. 재귀 적으로 작동하고 위의 줄 번호를 처리하려면 약간의 작업이 필요합니다.


6

으로 만 할 수는 없습니다 grep. 경우 ed'옵션은 S :

ed -s file << 'EOF' 
g/match/-5p\
+5p\
+5p
EOF  

스크립트는 기본적으로 / match /와 일치 할 때마다 그 앞에 5 줄, 그 후에 5 줄, 그 뒤에 5 줄을 인쇄합니다.


5
@ubashu 당신은 그것이 단순한 grep "grep으로 할 수 없습니다"를주는 OP에 더 도움이 될 것이라고 생각합니까? OP의 문제를 해결할 수있는 좋은 대안이라고 생각합니다. 도움말 센터에서 : "구체적으로 무엇을 요구하고 있습니까? 대답이 다음을 제공하는지 또는 실행 가능한 대안인지 확인하십시오. 대답은 '하지 마십시오'일 수 있지만 '대신 시도해보십시오'를 포함해야합니다. "
— JoL

ed이다 항상 있기 때문에, 대답 ed표준 텍스트 편집기입니다.
— 디저트

5
@ubashu grep대답은 아니지만 "X로 할 수는 없지만 Y로 할 수 있습니다"라는 대답은 OP의 질문에 대답 할뿐만 아니라 대안을 제공하기 때문에 여전히 유효한 대답입니다. 작동합니다. 올바른 답변 유형입니다.
— 토마스 워드

5
awk '/match/{system("sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME)}' infile

여기에 우리가 사용하는 AWK를 의 외부 호출하는 기능을 선 인쇄 명령을 AWK 패턴과 일치 5 일 개 이전과 경기 후 라인.system(command)sedmatch

구문은 간단합니다. 외부 명령 자체를 큰 따옴표와 스위치 안에 넣고 스위치에 정확하게 전달하려는 항목을 이스케이프하면 awk자체 옵션 과 관련된 모든 항목 이 따옴표 외부에 있어야합니다. 그래서 아래의 sed :

"sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME

로 번역 :

sed -n "NR-5p; NRp; NR+5p" FILENAME

NR패턴 match과 일치하는 행 번호 이며을 통과하는 FILENAME현재 처리중인 파일 이름awk 입니다.


2

@glenn의 예제 텍스트 파일을 사용하고 awk 대신 perl을 사용하십시오.

$ perl -n0E 'say /(.*\n)(?=(?:.*\n){4}(.*match.*\n)(?:.*\n){4}(.*\n))/g' ex

동일한 결과를 제공하지만 더 빠르게 실행됩니다.

a
f match
k
d
i match
n

João, 당신은 LQ 검토 대기열에 나타나고 @waltinator가 삭제하기로 투표 했으므로 다음에는 조금 더 장황하게됩니다 ... ;-) 또한 LQ 대기열에서 꺼내기 위해 +1합니다 : : P
— Fabby

1
@JJoao 저품질 검토 대기열. 귀하의 답변은 90 % 코드 였기 때문에 아마 거기에서 선택되었습니다.
— wjandrea

1
@JJoao 90 % 수치는 단지 그것을 설명하는 방법입니다. 어떤 휴리스틱이 실제로 사용되는지 모르겠습니다.
— wjandrea

1
메 노스 카페, 일식! @JJoao : D ;-) : D
— Fabby

1
@Fabby : Sem café nada funciona : D-아마 LCQ에 표시 될 것입니다 (= 커피 대기열이 낮음)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.