grep을 사용하여 일치하는 줄 위 또는 아래에 N 및 M 줄을 인쇄하는 방법은 무엇입니까?

grep을 사용하여 일치하는 줄 위 또는 아래에 N 및 M 줄을 인쇄하는 방법은 무엇입니까?

다음 내용(앞줄 번호 없음)이 포함된 잘 구성된 텍스트 파일이 있다고 가정해 보겠습니다.

 1 Mon Jun 9 00:11:47 CST 2014
 2 eth0      Link encap:Ethernet  HWaddr D4:BE:D9:F5:5C:0E
 3           inet addr:10.179.113.125  Bcast:10.179.113.127  Mask:255.255.255.248
 4           inet6 addr: fe80::d6be:d9ff:fef5:5c0e/64 Scope:Link
 5           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 6           RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
 7           TX packets:250825 errors:0 dropped:0 overruns:0 carrier:0
 8           collisions:0 txqueuelen:10000
 9           RX bytes:365792552 (348.8 MiB)  TX bytes:20648578 (19.6 MiB)
10           Interrupt:24 Memory:d6000000-d6012100
11 Tue Jun 10 05:11:47 CST 2014
12 eth1      Link encap:Ethernet  HWaddr D4:BE:D9:F5:5C:10
13           inet addr:10.254.4.1  Bcast:10.254.4.255  Mask:255.255.255.0
14           inet6 addr: fe80::d6be:d9ff:fef5:5c10/64 Scope:Link
15           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
16           RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0
17           TX packets:1206000723 errors:0 dropped:0 overruns:0 carrier:0
18           collisions:0 txqueuelen:10000
19           RX bytes:1596108082 (1.4 GiB)  TX bytes:2960952707 (2.7 GiB)
20           Interrupt:25 Memory:d8000000-d8012100

이제 필요한 것은 grep 키워드 "eth"를 사용하여 eth0 부분의 라인 1, #3, #6과 eth1 부분의 라인 #11, #13, #16을 필터링하는 것입니다.

Mon Jun 9 00:11:47 CST 2014    
inet addr:10.179.113.125  Bcast:10.179.113.127  Mask:255.255.255.248
RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
Tue Jun 10 05:11:47 CST 2014
inet addr:10.254.4.1  Bcast:10.254.4.255  Mask:255.255.255.0
RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0

어떻게 해야 하나요?

답변1

이것은 나에게 효과적입니다.

sed -n '/eth/{n;p;n;n;n;p;}' file
  • 검색 문자열eth
  • n;: 줄 건너뛰기, p;: 줄 인쇄
  • n;n;n;: 3줄 건너뛰고 다시 인쇄

편집하다:

위 줄, 뒤 줄, 그 뒤 세 줄이 인쇄됩니다.

sed -n -e '/eth/{x;1!p;g;$!n;p;n;n;n;p;D;}' -e h file

두 번째 질문: 아마도 명령을 20번 입력하지 않을 것 같습니다 n;.

답변2

이 awk 명령을 사용해 보세요.

$ awk '$1~/^eth/ {getline; print; getline; getline; getline; print}' file
          inet addr:10.179.113.125  Bcast:10.179.113.127  Mask:255.255.255.248
          RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
          inet addr:10.254.4.1  Bcast:10.254.4.255  Mask:255.255.255.0
          RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0

고쳐 쓰다:

$ awk '$1~/^eth/ {print previous; getline; print; getline; getline; getline; print}{previous=$0}' file
Mon Jun 9 00:11:47 CST 2014
           inet addr:10.179.113.125  Bcast:10.179.113.127  Mask:255.255.255.248
           RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
Tue Jun 10 05:11:47 CST 2014
           inet addr:10.254.4.1  Bcast:10.254.4.255  Mask:255.255.255.0
           RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0

답변3

다음은 인쇄할 줄을 선택하는 데 더 많은 유연성을 제공하는 Perl을 사용하는 다른 접근 방식입니다.

perl -n00E '
    @eth_records= grep {/eth/} split/(?=>Mon|Tue|Wed|Thu|Fri|Sat|Sun)/;
    @lines_to_print = qw{1 3 6};
    map { $_-- } @lines_to_print;
    $sep = "-"x80;
    for(@eth_records){
        say $sep;
        say for (split/\n/)[ @lines_to_print ];
        say $sep
    }' your_file

그러면 파일이 날짜 이름으로 시작하는 줄로 분할되고 일치하는 모든 기록의 줄 1, 3, 6이 인쇄됩니다./eth/

전체 파일을 메모리에 로드하므로 파일이 큰 경우에는 사용하지 마십시오.

답변4

몇 가지 제안이 있습니다 :

  • grep

    grep -P 'CST|inet |RX p' file
    

    CSTinet그러면 공백 또는 가 포함되거나 뒤에 오는 모든 줄 이 인쇄됩니다 RX pa. Perl 호환 정규 표현식을 활성화하여 이를 논리적 OR -P로 사용할 수 있습니다 . |다음 방법 중 하나를 사용하여 동일한 목표를 달성할 수도 있습니다.

    grep -E 'CST|inet |RX p' file
    

    또는

    grep  'CST\|inet \|RX p' file
    
  • sed

    sed -n '/CST\|inet \|RX p/p' file
    sed -rn '/CST|inet |RX p/p' file
    

    위와 같은 생각으로, -n모든 줄 인쇄를 억제하고 //p패턴과 일치하는 줄을 인쇄합니다.

  • perl

    Perl에서도 동일한 접근 방식을 사용할 수 있습니다.

     perl -ne 'print if /CST|inet |RX p/' file
    

    아니면 다음과 같은 일을 할 수도 있습니다.

     perl -ne '$k=1 if /CST/; print if $k==1||$k==3||$k==6; $k++' file
    

    여기서는 $k행이 일치하면 변수가 1로 설정되고 CST각 행을 읽은 후 1씩 증가됩니다. $k행의 값이 1,3 또는 6이면 행을 인쇄합니다 . 이는 보다 확장 가능한 접근 방식입니다.

    또 다른 방법은 인쇄하려는 줄 번호를 알고 있다고 가정하고 직접 인쇄하는 것입니다( $.현재 줄 번호).

    perl -ne 'print if $.==1||$.==3||$.==6||$.==11||$.==13||$.==16' file
    

    또는 좀 더 관용적으로 말하면:

    perl -ne '@d=(1,3,6,11,13,16); print if $.~~@d' file
    

    마지막으로 전체 파일을 메모리에 로드하고 관심 있는 줄만 인쇄할 수도 있습니다.

    perl -e '@F=<>; print @F[0,2,5,10,12,15]' file
    
  • awk

    awkNR현재 줄 번호가 어디에 있는지 동일한 기본 접근 방식을 사용할 수 있습니다 .

    awk '/CST|inet |RX p/' file
    

    또는

    awk '{if(/CST/){k=1} if(k==1||k==3||k==6){print} k++;}' file
    

    또는

    awk 'NR==1||NR==3||NR==6||NR==11||NR==13||NR==16' file
    

관련 정보