存储磁盘信息 - 将多个输入值替换为输出文件

存储磁盘信息 - 将多个输入值替换为输出文件

我想将以下有关存储磁盘的输入替换为以下格式的输出: 下面的脚本几乎对我有用。但这对T0不起作用。在“replaceTier”函数中正确读取数字末尾的 0 似乎存在问题。

你能帮我改正吗?提前致谢。

**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,这在replaceTier表中排在第一位,因此 110 将转换为 T1(来自 1:T1 映射)而不是 T0。

相反,您想要对要翻译的数字进行完全匹配,因此删除.*并添加$锚点(匹配行尾)以确保只有确切的数字匹配:

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, sed, cut, xargs),因此生成外部进程的大量开销也消失了。

但即使在这种情况下,也有改进的空间,通过使用关联数组 for 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表的大小变得更大时。

相关内容