ディスク情報の保存 - 複数の入力値を出力ファイルに置き換える

ディスク情報の保存 - 複数の入力値を出力ファイルに置き換える

ストレージディスクへの次の入力を次の形式の出力に置き換えたいと思います。以下のスクリプトはほぼ効果的でした。しかし、これはT0では機能しません。 "replaceTier"関数で数字の終わりのゼロを正しく読み取るのに問題があるようです。

校正をお手伝いできますか?よろしくお願いします。

**INPUT IN FILE:**
displayName=00:19:78
sizeInKB=26214720
dpPoolID=1
displayName=00:FE:B0
sizeInKB=2251536384
dpPoolID=110
displayName=00:FE:B1
sizeInKB=2251536384
dpPoolID=110



**EXPECTED OUTPUT:**
1978,T1
FEB0,T0
FEB1,T0



replaceTier=(
    {1,11,12,13,14,15,16,17,18,19,51,61,71,81,100}:T1
    {2,21,22,23,24}:T2
    3:T3
    {10,110}:T0
    90:SVC_T1
    91:SVC_T2
    92:SVC_T1
)
#
while read -r name serial model uid
 do
  cat "$DIR"/"$name"_disks.log | grep -v 'sizeInKB' | cut -d "=" -f2 | sed 's/\://g' | xargs -n2 | sed 's/\ /\,/g' | cut -c 3- | grep -v ',-1' > "$DIR"/"$name"_output.log
  for row in "${replaceTier[@]}"; do
    original="$(echo $row | cut -d: -f1)";
    new="$(echo $row | cut -d: -f2)";
    sed -i -e "s/,${original}.*/,${new}/g" "$DIR"/"$name"_output.log;
  done
done < /storage/logs/HDSlist.txt

答え1

ありがとうございます。あなたは正しいです。 '.*' は '$' に置き換える必要があります。今はうまくいきます。返品そこ私にも必ず必要な情報を見つけた。

  sed -i -e "s/,${original}$/,${new}/g" "$DIR"/"$name"_output.log;

あなたの努力に感謝します。

答え2

問題は正規表現の終わりにあるワイルドカードです。

s/,${original}.*/,${new}/g

.*110 はテーブルの最初の 11 または 1 と一致するため、replaceTier110 は T0 ではなく T1 (1:T1 マッピングで) に変換されます。

代わりに、翻訳したい数字と正確に一致するものが必要なので、正確な数字のみを一致させるようにアンカー(行末と一致)を削除して.*追加してください。$

s/,${original}\$/,${new}/g

ところで、ログファイルの解析が複雑すぎるようです。スクリプトを使用すると仮定すると、bash次のようになります。

while read -r displayName; do
  # Read two more rows of data from the
  # input file.
  read -r sizeInKB   # ignored
  read -r dpPoolID
  # Process displayName, remove everything
  # up to the first ":", then drop the
  # remaining ":" in the middle.
  displayName=${displayName#*:}
  displayName=${displayName/:/}
  # Look up dpPoolID in replaceTier.
  tier=""
  for row in "${replaceTier[@]}"; do
    # Split row into id:tier.
    id=${row%%:*}
    if [[ "$dpPoolID" = "$id" ]]; then
      tier=${row#*:}
      break
    fi
  done
  if [[ -n "$tier" ]]; then
    # Only print when tier was found, so skip
    # invalid dpPoolIDs such as -1, etc.
    printf "%s,%s\n" "$displayName" "$tier"
  fi
done <"$DIR"/"$name"_disks.log >"$DIR"/"$name"_output.log

これは、同じファイルへの複数の読み取りと書き込みを防ぐだけでなく、組み込みbash関数(no 、、、、grep)のみを使用するため、外部プロセスの作成に伴う多くのオーバーヘッドがなくなりました。sedcutxargs

ただし、この場合でも連想配列を使用すると改善の余地がありますreplaceTier。この場合、各行で完全に繰り返すのではなく、直接クエリを実行できます。

以下を使用して、これらの連想配列を定義できます。

replaceTier=(
    [1]=T1
    [12]=T1
    [13]=T1
    [14]=T1
    ...
    [100]=T1
    [2]=T2
    [21]=T2
    ...
    [24]=T2
    [3]=T3
    [10]=T0
    [110]=T0
    [90]=SVC_T1
    [91]=SVC_T2
    [92]=SVC_T1
)

この場合、最も内側のforループを直接照会に簡素化できます。

tier=${replaceTier[$id]}

これは、特にテーブルサイズが大きくreplaceTierなるほど効率的です。

関連情報