awk でできること:
awk '{a[i++]=$0};/-----/{++j};j==3{t="";for(k=0;k<i;++k)t=t a[k]"\n";b[++l]=t;i=j=0}END{for(i=l;i;--i)printf "%s", b[i]}' file
出力:
----------------------------------------------------------------
date time hostname cpu ram / /opt
----------------------------------------------------------------
2013/09/08 15:40:00 server1 20% 30% 50% 70%
2013/09/08 15:40:00 server2 15% 21% 49% 72%
2013/09/08 15:40:00 server3 20% 40% 40% 75%
----------------------------------------------------------------
----------------------------------------------------------------
date time hostname cpu ram / /opt
----------------------------------------------------------------
2013/09/08 15:35:00 server1 15% 30% 50% 70%
2013/09/08 15:35:00 server2 18% 21% 49% 72%
2013/09/08 15:35:00 server3 15% 40% 40% 75%
----------------------------------------------------------------
----------------------------------------------------------------
date time hostname cpu ram / /opt
----------------------------------------------------------------
2013/09/08 15:30:00 server1 20% 30% 50% 70%
2013/09/08 15:30:00 server2 10% 21% 49% 72%
2013/09/08 15:30:00 server3 15% 40% 40% 75%
----------------------------------------------------------------
無効なデータを除外できる別のより安全なバリエーション:
awk '/^-----+$/{++j};!j{next};{a[i++]=$0}j==3{t="";for(k=0;k<i;++k)t=t a[k]"\n";b[++l]=t;i=j=0}END{for(i=l;i;--i)printf "%s", b[i]}' file
行数に基づく別のもの:
awk '{a[i++]=$0}i==7{t="";for(k=0;k<i;++k)t=t a[k]"\n";b[++l]=t;i=0}END{for(i=l;i;--i)printf "%s", b[i]}' file
もう少し簡単:
awk '{a[i++]=$0}i==7{t="";for(i=0;i<7;++i)t=t a[i]"\n";b[++j]=t;i=0}END{for(;j;--j)printf "%s", b[j]}' file
同じコンセプトでBashでそれを行う別の簡単な方法:
( IFS=$'\n'; while read -r A[I++]; do [[ I -eq 7 ]] && { B[++J]="${A[*]}"; I=0; }; done; for ((;J;--J)); do echo "${B[J]}"; done; ) < file
Rubyのもう1 つの真のワンライナー:
ruby -e '$stdin.readlines().each_slice(7).entries.reverse.each { |b| puts b; }' < file