bash의 첫 번째 필드에서 순서대로 행을 계산하는 방법


9

다음은 INPUT의 스 니펫입니다.

...
####################
Bala Bela;XXXXXX12345;XXXXXX12345678;A
SERVER345Z3.DOMAIN.com0
SERVER346Z3.DOMAIN.com0
SERVER347Z3.DOMAIN.com0
SERVER348Z3.DOMAIN.com0
ssh-dss ...pubkeyhere...
####################
Ize Jova;XXXXXX12345;XXXXXX12345;A
SERVER342Z3.DOMAIN.com0
SERVER343Z3.DOMAIN.com0
SERVER345Z3.DOMAIN.com0
ssh-rsa ...pubkeyhere...
...

그리고 여기 내가 필요한 OUTPUT의 스 니펫이 있습니다.

Bala Bela;XXXXXX12345;XXXXXX12345678;A
4
Ize Jova;XXXXXX12345;XXXXXX12345;A
3

따라서 입력에서 OUTPUT이 필요하므로 "SERVER"로 시작하는 행이 주어진 사용자에게 얼마나 많은 행이 있는지 볼 수 있습니다 (예 : "Bala Bela; XXXXXX12345; XXXXXX12345678; A"). bash에서 어떻게 할 수 있습니까?


독립형 Bash 여야합니까, 아니면 다른 도구를 사용할 수 있습니까 (grep, awk, perl ...)?
ire_and_curses

명시 적으로 언급하지 않는 한 bash 스크립팅 질문은 grep, awk, sed, perl 및 나머지 모든 표준 도구를 허용한다고 가정합니다.
cas

답변:


6
{
i=0
while IFS= read -r line; do
  case "$line" in
    ssh*|'##'*)
      ;;
    SERVER*)
      ((++i))
      ;;
    *)
      if ((i>0)); then echo $i;i=0; fi
      echo "$line"
      ;;
  esac
done
if ((i>0)); then echo $i;i=0; fi
} <inputfile >outputfile

펄 원 라이너에서 동일

perl -nle '
  BEGIN{$i=0}
  next if/^(ssh|##)/;
  if(/^SERVER/){++$i;next}
  print$i if$i>0;
  $i=0;
  print;
  END{print$i if$i>0}' inputfile >outputfile

그리고 골프

perl -nle's/^(ssh|##|(SERVER))/$2&&$i++/e&&next;$i&&print$i;$i=!print}{$i&&print$i' inputfile >outputfile

와. perl is amazing : D
gasko peter

5

이 버전은 grep줄 의 정규 표현식과 일치하지 않는 모든 행을 계산합니다 .

#! /usr/bin/perl 

# set the Input Record Separator (man perlvar for details)
$/ = '####################';

while(<>) {
    # split the rows into an array
    my @rows = split "\n";

    # get rid of the elements we're not interested in
    @rows = grep {!/^#######|^ssh-|^$/} @rows;

    # first row of array is the title, and "scalar @rows"
    # is the number of entries, so subtract 1.
    if (scalar(@rows) gt 1) {
      print "$rows[0]\n", scalar @rows -1, "\n"
    }
}

산출:

발라 벨라; XXXXXX12345; XXXXXX12345678; A
4
이즈 요바; XXXXXX12345; XXXXXX12345; A
삼

당신은 경우 에만 다음 '서버'로 시작하는 라인을 계산하려면 :

#! /usr/bin/perl 

# set the Input Record Separator (man perlvar for details)
$/ = '####################';

while(<>) {
    # split the rows into an array
    my @rows = split "\n";

    # $rows[0] will be same as $/ or '', so get title from $rows[1]
    my $title = $rows[1];

    my $count = grep { /^SERVER/} @rows;

    if ($count gt 0) {
      print "$title\n$count\n"
    }
}

5
sed -n ':a /^SERVER/{g;p;ba}; h' file | uniq -c | 
  sed -r 's/^ +([0-9]) (.*)/\2\n\1/'

산출:

Bala Bela;XXXXXX12345;XXXXXX12345678;A
4
Ize Jova;XXXXXX12345;XXXXXX12345;A
3

접두사 개수가 정상인 경우 :

sed -n ':a /^SERVER/{g;p;ba}; h' file |uniq -c

산출:

  4 Bala Bela;XXXXXX12345;XXXXXX12345678;A
  3 Ize Jova;XXXXXX12345;XXXXXX12345;A

4

awk대안 :

/^#{15,}/ {           # if line starts with 15 or more number signs
  if(k) {             # if any key found
    print k RS n      # print it and occurrences of SERVER
    n=0
  }
  getline             # key is on the next line
  k = $0
  next                # move to next record
} 

/SERVER/ { n++ }      # count occurrences of SERVER
END { print k RS n }  # print last record

한 줄에 모두 :

awk '/^#{15,}/ { if(n>0) { print k RS n; n=0 }; getline; k = $0; next } /SERVER/ { n++ } END { print k RS n }'

2

따라서 출력이 각 "버킷"에서 이미 정렬 된 경우 첫 번째 N 문자 만 확인하여 uniq을 직접 적용 할 수 있습니다.

cat x | uniq -c -w6

SERVER는 줄의 시작 부분에서 6 자로 구성되므로 N == 6입니다. 이 출력 (필요한 출력과 약간 다릅니다)으로 끝납니다.

  1 ####################
  1 Bala Bela;XXXXXX12345;XXXXXX12345678;A
  4 SERVER345Z3.DOMAIN.com0
  1 ssh-dss ...pubkeyhere...
  1 ####################
  1 Ize Jova;XXXXXX12345;XXXXXX12345;A
  3 SERVER342Z3.DOMAIN.com0
  1 ssh-rsa ...pubkeyhere...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.