간단한 해결책

간단한 해결책

다음과 같은 파일이 있습니다

header start
stuff
header end
pos LV file LVG size
1   a1 AAA  BBB 100
2   b1 AAC  BBB 1000
3   a3 AAB  BBB 47
4   b6 AAC  BBB 1000

a두 번째 열부터 시작하는 행의 개수를 계산해야 합니다. 구글링해서 이거 찾았는데

awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"\n"a[i]-1}' file

하지만 출력이 행 수에 불과하도록 콘텐츠를 필터링해야 합니다. 다음을 추가했습니다.

awk '/LVG/ || $2 ~ "^a"' file | awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"\n"a[i]-1}' | tail -1

awk이것이 나에게 필요한 작업이지만, 이 모든 것이 하나의 명령으로 수행될 수 있는지 궁금합니다 .

답변1

가장 기본적인 요구 사항은 다음과 같습니다.

awk '$2~/^a/{c++} END{print c+0}'

두 번째 열을 확인하고 정규식 비교로 시작하는지 확인 a하고 counter 를 증가시킵니다 c. 파일 끝에 카운터가 인쇄됩니다. 실제로 증가하지 않는 숫자 도 인쇄되도록 보장하기 위해 c이미 0이 아닌 경우 c+0변경되지 않는다고 인쇄하지만 아직 초기화되지 않은 경우 숫자로 해석되도록 합니다.cc

이제 "헤더" 섹션을 방해하는 "떠나는" 토큰이 없는지 확인하기 위해 첫 번째 검사는 첫 번째 열이 정수인지 확인하는 것입니다.

awk '$1+0==$1 && $2~/^a/{c++} END{print c+0}'

여기서의 아이디어는 숫자인 경우 $1+0산술적으로 "아무것도 추가하지 않음"으로 해석되지만$1awk문자 추가0"텍스트"인 경우 $1+0숫자인 경우에만 변경됩니다.$1

더 복잡한 검사를 위해 행을 즉시 건너뛰는 것 외에도 "헤더 끝" 행이 나타날 때까지 행이 고려되지 않도록 억제할 수 있습니다.

awk 'f==2&&$2~/^a/{c++} f==1&&NF{f++} $0=="header end"{f=1} END{print c+0}'

행이 발견되면 플래그가 f1로 설정되고, 헤더 다음의 비어 있지 않은 첫 번째 행으로 설정되며, 두 번째 열이 확인되는 행에만 설정됩니다.header end2f2

답변2

제가 제안하는 것은 awk해결책이 아니라 grep레코드 구조에 의존하는 것입니다.

$ grep "^[0-9]\+[[:blank:]]\+a[0-9]\+[[:blank:]]\+[A-Z]\+[[:blank:]]\+[A-Z]\+[[:blank:]]\+[0-9]\+$" file | wc -l
2

답변3

awk 'NR==1 ,/^header end$/ { next };
    !skip_hdr              { skip_hdr=1; next }
    ($2 ~ /^a/)            { count++ }
END{ print count+0 }' infile
  • NR==1 ,/^header end$/ { next }:
    파일의 시작 부분에서 첫 번째 줄로 이동합니다 header end. 이는 다음 줄을 건너뜁니다.

    헤더 시작
    물건
    머리와 꼬리
    

  • !skip_hdr { skip_hdr=1; next }:
    헤더 행 건너뛰기pos LV file LVG size.

  • ($2 ~ /^a/) { count++ }: 두 번째 열이 문자로 시작하는 행 수를
    계산합니다 (대소문자 구분 안 함).a

  • END{ print count+0 }:
    최종 카운트 값을 인쇄합니다.

답변4

간단한 해결책

설명과 일치:두 번째 열부터 시작하는 행 개수 계산이것으로 충분합니다:

awk '$2 ~ /^a/ { count++ } END {print count}' file 

grep(더 빨라야 함) 명령을 사용할 수도 있습니다.

grep -c '^[0-9][0-9]* *a' test.txt

이는 또한 첫 번째 필드가 숫자(게시된 예에서 필요한 것이라고 가정)이고 필드 구분 기호가 공백이어야 한다는 점에서 더 구체적입니다.

더 깊이 보기

하지만 게시한 첫 번째 솔루션은 다음과 같습니다.

awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"\n"a[i]-1}' file

완전히 다른 일을 했습니다.

이 파일에 다음을 입력하십시오.

> cat file
header start
stuff
header end
pos1 LV file LVG size
1   a1 AAA  BBB 100
2   b1 AAC  BBB 1000
3   a3 AAB  BBB 47
4   b6 AAC  BBB 1000
5   c9 BBA  CBA 20
pos2 LV file LVG size
1   a1 AAA  BBB 100
2   b1 AAC  BBB 1000
pos3 LV file LVG size
1   a1 AAA  BBB 100
2   b1 AAC  BBB 1000
3   a3 AAB  BBB 47

게시한 코드는 각 (다른) 헤더에 대한 결과를 인쇄합니다.

> awk '/LVG/{p=$0} {a[p]++} END{for(i in a) print i"=="a[i]-1}' test.txt 
==2
pos1 LV file LVG size==5
pos3 LV file LVG size==3
pos2 LV file LVG size==2

즉, 빈 제목에 2줄, 제목 "pos1" 뒤에 5줄 등...

이런 계산이 필요한지 모르겠습니다. 카운트에서 1을 빼는 이유도 불분명합니다.

유일한 추가 요구 사항은 두 번째 필드만 계산하는 것입니다.a

$ awk '/LVG/{p=$0} $2 ~ /^a/ {a[p]++} END{for(i in a) print i"=="a[i]}' test.txt
pos1 LV file LVG size==2
pos3 LV file LVG size==2
pos2 LV file LVG size==1

첫 번째 필드도 숫자여야 하는 경우(위의 grep 명령과 유사):

$ awk '/LVG/{p=$0} ($1+0!=0)&&($2~/^a/) {a[p]++} END{for(i in a) print i"=="a[i]}' test.txt
pos1 LV file LVG size==2
pos3 LV file LVG size==2
pos2 LV file LVG size==1

관련 정보