我想将以下有关存储磁盘的输入替换为以下格式的输出: 下面的脚本几乎对我有用。但这对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
表的大小变得更大时。