패턴 일치 전 / 후의 총 라인 수 계산


9

IP 주소 목록이 길고 순서가 맞지 않습니다. 특정 IP 주소 전후에 몇 개의 IP 주소가 있는지 찾아야합니다. 어떻게하면 되나요?


IP가 중복되어 있습니까?
cuonglm

아니요. 모든 IP 주소는 고유합니다.
Mandar Shinde

IP 주소 전 / 후는 무엇을 의미합니까? 특히, IPv4 및 IPv6 주소가 모두 있습니까? 그들은 어떻게 비교합니까?
vinc17

파일을 정렬해야합니까?
cuonglm

2
@ vinc17-파일에는 IP 주소 (IPv4) 만 포함되며 다른 데이터는 포함되지 않습니다. 총 1000 개의 IP 주소가 있고 300 번째 위치에서 일치하는 것이 있으면 일치 전 299 행과 일치 후 700 행이 있음을 의미합니다.
Mandar Shinde

답변:


8

일치를 포함하여 일치 전후의 줄 수 (예 : 일치를 제외하려면 결과에서 1을 빼야 함) :

sed -n '0,/pattern/p' file | wc -l
sed -n '/pattern/,$p' file | wc -l

그러나 이것은 특히 IP 주소와 관련이 없습니다.


4

아마도 가장 쉬운 방법은

sed -n '/pattern/{=; q;}' file

오류를 지적 해 주셔서 감사합니다 @JoshepR


패턴이 발생한 줄 번호 만 인쇄합니다.
Joseph R.

@JosephR. - 아니, 인쇄 마다 있는 행 번호 모든 일치가 발생합니다.
mikeserv

@mikeserv 알고 있지만 OP 는 IP 주소가 고유하다고 지정 했습니다. 또한 OP는 일치하는 행 번호를 원하지 않습니다. 패턴이 발생하기 전의 라인 수 패턴 이후의 라인 수를 원합니다 .
Joseph R.

@JosephR-그 수에 도달하는 가장 빠른 방법은 줄 번호를 계산하는 dc것입니다. 아마 이것을 직접 직접 파이프 할 것입니다.
mikeserv

@ mikeserv 나는이 답변의 정보가 유용하지 않다고 주장하는 것이 아니라이 코드 자체가 OP가 원하는 것을 수행하지 않는다고 말하는 것입니다.
Joseph R.

3

나는 이것을 가장 좋아한다고 생각하지만이 두 가지 방법을 사용했습니다.

: $(( afterl=( lastl=$(wc -l <~/file) ) - 2 -
  $(( beforel=( matchl=$(sed -n "/$IP/{=;q;}" <~/file) ) - 1
)) ))
for n in last match afters befores
do  printf '%s line%s :\t%d\n' \
        "${n%s}" "${n##*[!s]}" $((${n%s}l))
done

모든 변수를 현재 쉘 변수로 저장하고 출력을 위해 for 루프에서 평가합니다. 파일의 총 줄 수를 계산하고와 wc일치하는 첫 번째 줄 번호를 가져옵니다 sed.

출력 :

last line :     1000
match line :    200
after lines :   799
before lines :  199

나는 또한했다 :

sed -n "/$IP/=;\$=" ~/file |  
tr \\n \  | { 
IFS=' ' read ml ll 
printf '%s line%s:\t%d\n' \
    last '' $((ll=${ll##* }))
    match '' $ml \
    after s "$((al=ll-ml-1)) \ 
    before s $((bl=ml-1))
}

sed일치하는 마지막 줄 번호 만 인쇄 한 다음 tr중간 \n줄 바꿈을, 그리고 read첫 번째 sed결과 $ml와 다른 모든 결과를 읽습니다 $ll. 가능한 여러 개의 일치 사례는 $ll나중에 다시 설정할 때의 확장 결과에서 마지막 결과를 제외한 모든 결과를 제거하여 처리됩니다 .

출력 :

last line :     1000
match line :    200
after lines :   799
before lines :  199

두 가지 방법 모두 다음과 같은 방법으로 생성 된 파일에서 테스트되었습니다.

IP='some string for which I seek' 
for count in 1 2 3 4 5 
do  printf '%.199d%s\n' 0 "$IP" 
done | tr 0 \\n >~/file 

행 번호로 수행합니다.

  1. 검색 문자열을 설정합니다
  2. 여러 번 일치하도록 다섯 번 반복
  3. 199 개의 0을 인쇄 한 "$IP"다음 \newline 을 인쇄합니다.
  4. 파이프 출력 -0 tr\newlines로 변환 한 다음~/file

2

이를 수행하는 약간의 Perl 코드가 있습니다.

perl -ne '
     if(1 .. /192\.168\.1\.1/) { $before++ }
     else                      { $after++  }
     $before--; # The matching line was counted
     END{print "Before: $before, After: $after\n"}' your_file

IP가 포함 된 줄 전후의 총 줄 수를 계산합니다 192.168.1.1. 원하는 IP로 교체하십시오.

배쉬 만 사용하면 :

before=0
match=0
after=0
while read line;do
    if [ "$line" = 192.168.1.1 ];then
        match=1
    elif [ $match -eq 0 ];then
        before=$(($before+1))
    else
        after=$(($after + 1))
    fi
done < your_file
printf "Before: %d, After: %d\n" "$before" "$after"

BASH가 선호됩니다.
Mandar Shinde

2
@Joseph R .: $.카운터 대신에 왜 사용 하지 않습니까?
cuonglm

@Gnouc 물론입니다. 나는 이것이로 설정 $after하는 것보다 더 읽기 쉽다고 생각 합니다 $. - $before.
Joseph R.

아니요, 의미하는 경우 : 일치하는 경우 print $. - 1에 저장 $.하십시오 $tmp. 인쇄를 종료 $. - $tmp합니다. 따라서 우리는 전후에 카운터가 필요하지 않습니다. 물론 그것은 당신보다 읽기 어렵습니다.
cuonglm

@MandarShinde 편집 내용을 참조하십시오. 순수한 Bash 답변을 추가했습니다.
Joseph R.

2

다음 명령을 시도했지만 약간 복잡하지만 정확한 결과를 제공합니다.

후:

a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l

전에:

echo "`cat -n file | grep <Pattern> | awk '{print $1}'`-1" | bc -l

2

awk마지막 일치 전후 줄 수를보고 하는 솔루션

awk '/192\.168\.1\.1/{x=NR};{y=NR} END{printf "before-%d, after-%d\n" , x-1, y-x}'  file

1

Grep특정 패턴이 발견 된 횟수를 계산할 수있는 기능이 있습니다. -c명령을 사용하면 그렇게됩니다. -cand -v명령을 사용하면 특정 패턴과 일치하지 않는 횟수를 계산합니다.

예:

grep -c -v <pattern> file

따라서 다음과 같은 것을 시도하면

grep -c -v 192.168.x.x file.log 작동해야합니다.


대상 IP의 발생 횟수를 계산합니다. 이것은 OP가 요구 한 것이 아닙니다.
Joseph R.

방금 편집 한 결과, 특정 IP 전후에 다른 모든 IP를 계산하도록 요청하는 경우 편집 작업이 필요합니다.
ryekayo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.