디스크 정보 저장 - 여러 입력 값을 출력 파일로 대체

디스크 정보 저장 - 여러 입력 값을 출력 파일로 대체

스토리지 디스크에 대한 다음 입력을 다음 형식의 출력으로 바꾸고 싶습니다. 아래 스크립트는 거의 효과적이었습니다. 그러나 이것은 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과 일치 시키므로 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, sed, cut, xargs)만 사용하므로 외부 프로세스를 생성하는 데 따른 많은 오버헤드가 사라졌습니다.

하지만 이 경우에도 연관 배열을 사용하면 개선의 여지가 있습니다 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커질수록 더욱 효율적입니다.

관련 정보