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.