区切り記号間のすべての行数の計算

区切り記号間のすべての行数の計算

次の例では、各デバイスに接続されているアドレスの数を計算したいと思います。 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

おすすめ記事