다음과 같은 파일이 있습니다
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
변경되지 않는다고 인쇄하지만 아직 초기화되지 않은 경우 숫자로 해석되도록 합니다.c
c
이제 "헤더" 섹션을 방해하는 "떠나는" 토큰이 없는지 확인하기 위해 첫 번째 검사는 첫 번째 열이 정수인지 확인하는 것입니다.
awk '$1+0==$1 && $2~/^a/{c++} END{print c+0}'
여기서의 아이디어는 숫자인 경우 $1+0
산술적으로 "아무것도 추가하지 않음"으로 해석되지만$1
awk
문자 추가0
"텍스트"인 경우 $1+0
숫자인 경우에만 변경됩니다.$1
더 복잡한 검사를 위해 행을 즉시 건너뛰는 것 외에도 "헤더 끝" 행이 나타날 때까지 행이 고려되지 않도록 억제할 수 있습니다.
awk 'f==2&&$2~/^a/{c++} f==1&&NF{f++} $0=="header end"{f=1} END{print c+0}'
행이 발견되면 플래그가 f
1로 설정되고, 헤더 다음의 비어 있지 않은 첫 번째 행으로 설정되며, 두 번째 열이 확인되는 행에만 설정됩니다.header end
2
f
2
답변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