아래 예에서는 각 장치에 연결된 주소 수를 계산하고 싶습니다. awk나 sed를 사용하는 것이 더 좋습니다.
/dev/1
addr1 sometext sometext sometext
addr2 sometext sometext sometext
addr3 sometext sometext sometext
/dev/2
wwpn1 sometext sometext sometext
wwpn2 sometext sometext sometext
/dev/3
addr1 sometext sometext sometext
addr2 sometext sometext sometext
addr3 sometext sometext sometext
addr4 sometext sometext sometext
/dev/4
addr1 sometext sometext sometext
다음은 일치 항목을 제공하지만 수동으로 명령을 여러 번 실행하는 것 외에는 모든 장치에 대해 이를 증가시킬 수 없습니다.
sed -n '/\/dev\/1/,/\/dev\/2/'p
/dev/1
addr1 sometext sometext sometext
addr2 sometext sometext sometext
addr3 sometext sometext sometext
/dev/2
내가 원하는 것은 모든 장치를 반복하는 것입니다. 다음과 같습니다.
for i in `grep 'dev' somefile`; do sed -n '/$i/,/$insersecondmatchhere/'p ; done
문제는 명령 시작 부분의 for 루프에서 $insertsecondmatchhere 변수를 가져오는 방법을 잘 모르겠다는 것입니다.
답변1
이것은 간단한 접근 방식입니다 awk
. /dev/[0-9] 모드가 있으면 기존에 저장된 모드와 카운트를 덤프한 다음 장치와 카운트를 재설정하고 그렇지 않으면 카운터를 증가시킵니다. EOF에 도달하면 저장된 모드와 개수를 덤프합니다.
#!/bin/awk -f
{
if ( /\/dev\/[0-9]/ ) {
if (dev) { print dev, count; };
dev=$0;
count=0;
} else {
++count;
}
}
END {
print dev, count;
}
여러 awk 버전과 terdon의 perl 솔루션이 있으므로 이것은 초기 방향인 것처럼 보이기 때문에 보기 흉한 bash + grep + sed 솔루션입니다.
#!/usr/bin/env bash
declare -a devs
devs=( $(grep ^/dev/ input) )
for ((i=0; i < ${#devs[@]} - 1; i++)); do
start=${devs[i]}
end=${devs[i+1]}
start=${start//\//\\\/}
end=${end//\//\\\/}
count=$(sed -n "/^$start/,/^$end/p" input | wc -l)
count=$(( count - 2 ))
echo for ${devs[i]}, count is $count
done
start=${devs[i]}
start=${start//\//\\\/}
count=$(sed -n "/^$start/,\$p" input | wc -l)
count=$(( count - 1 ))
echo for ${devs[i]}, count is $count
주요 트릭은 장치 이름을 sed
.
답변2
이 같은?
awk -v RS="/dev/" 'NR!=1 {print "/dev/"$1":"NF-1}' file.txt
답변3
또 다른 awk
방법:
$ awk '{if(/^\//){n=$0;}else{l[n]++}}END{for(n in l){print n" : "l[n]}}' file
/dev/1 : 3
/dev/2 : 2
/dev/3 : 4
/dev/4 : 1
n
현재 행이 로 끝나면 , 그렇지 않으면 연관 배열에 저장된 현재 값만큼 /
증가됩니다 . 그러면 각 섹션의 행 수가 계산됩니다. 전체 파일을 읽은 후 청크로 각각 (섹션 이름, 줄 수)과 해당 섹션의 줄 수를 인쇄합니다 .l[n]
l
n
END{}
n
dev
골프를 칠 수 있습니다:
awk '{/^\//?n=$0:l[n]++;}END{for(n in l){print n" : "l[n]}}' file
(golf)Perl에서도 동일한 아이디어가 적용됩니다.
$ perl -lne'/^\//?$n=$_:$l{$n}++;}{print"$_ : $l{$_}"for keys(%l)' file
/dev/2 : 2
/dev/1 : 3
/dev/3 : 4
/dev/4 : 1
다음으로 확장 가능:
perl -lne 'if(/^\//){$n=$_}
else{ $l{$n}++ }
END{print"$_ : $l{$_}" for keys(%l)}' file