반올림 포함

반올림 포함

왼쪽의 계층 구조를 가장 잘 유지하고 오른쪽의 크기 값을 정렬하려면 어떻게 해야 합니까?
또한 동시에 크기를 한 자리 또는 두 자리로 반올림하고 싶습니다.
시도해 보았지만 printf이 형식을 유지하는 방법을 알 수 없습니다.

$ port rdeps mtr 2>/dev/null | sed -E "1 s/.*of (.*) @.*/\1/" | while IFS= read -r line; do echo -e "$line" \\t\\t\\t\\t $(port space --units MiB --total $line 2>/dev/null | cut -d ' ' -f 1-2); done
mtr                  0.088 MiB
  pkgconfig                  0.615 MiB
    libiconv                 6.270 MiB
      gperf                  0.0 MiB
  glib2                  46.092 MiB
    xz               1.679 MiB
      gettext                24.825 MiB
        expat                1.109 MiB
        ncurses                  15.171 MiB
    libxml2                  10.405 MiB
      zlib               0.721 MiB
    libffi               0.141 MiB
    pcre                 5.954 MiB
      bzip2                  0.647 MiB
      libedit                0.795 MiB

이것은 다음과 같아야합니다

mtr                          0.08 MiB
  pkgconfig                  0.61 MiB
    libiconv                 6.27 MiB
      gperf                  0.00 MiB
  glib2                     46.09 MiB
    xz                       1.67 MiB
      gettext               24.82 MiB
        expat                1.10 MiB
        ncurses             15.17 MiB
    libxml2                 10.40 MiB
      zlib                   0.72 MiB
    libffi                   0.14 MiB
    pcre                     5.95 MiB
      bzip2                  0.64 MiB
      libedit                0.79 MiB

답변1

이를 수행하는 방법에는 여러 가지가 있습니다.

반올림 포함

아시다시피 printf이는 인쇄물의 서식을 지정하는 데 훌륭한 도구입니다.  %f"부동소수점 숫자", 즉 정수가 아닌 숫자, 즉 소수 부분이 포함된 숫자를 출력하기 위한 형식입니다. 모든 printf 형식과 마찬가지로 뒤에 오는 숫자(정수!)는 % 공백을 포함할 수 있는 형식화된 출력의 전체 길이를 지정합니다. 숫자 뒤에는 마침표(.) 및 표시할 소수점 이하 자릿수를 지정하는 다른 숫자(소수점 오른쪽의 숫자)입니다. 예를 들어 다음 명령은

printf "%12.2f\n" 1000000
printf "%12.2f\n" 1000
printf "%12.2f\n" 1
printf "%12.2f\n" 1.2345
printf "%12.2f\n" 1.6789

출력을 생성합니다

  1000000.00
     1000.00
        1.00
        1.23
        1.68

1.6789있으니 참고해주세요반올림도착하다 1.68.

따라서 다음 명령을 사용하여 원하는 결과를 얻을 수 있습니다.

port rdeps mtr 2>/dev/null | sed -E "1 s/.*of (.*) @.*/\1/" |
     while IFS= read -r line
     do
         space="$(port space --units MiB --total $line 2>/dev/null | cut -d ' ' -f 1-2)"
         space_num=${space% *}
         space_mib=${space#* }
         printf "%-20s%12.2f %s\n" "$line" "$space_num" "$space_mib"
     done

space=$(…)명령은 port space우리가 사용했던 명령을 대체한 것일 뿐이지만 결과(예 0.088 MiB: 와 같은 모양)가 임시 변수에 할당되어 있습니다 space. 그런 다음 공백 문자 앞 부분(예: 숫자, 이 경우) 으로 space_num=${space% *}설정하고 , 공백 문자 뒤 부분(예: 단위)으로 설정합니다 . 마지막으로 숫자를 소수점 이하 두 자리까지 표시하기 위해 모든 조각을 함께 붙였고 , 가장 가까운 100분의 1 자리로 반올림하고 소수점에 정렬했습니다(이전 예에서처럼). 귀하의 데이터에 대해 이것은 다음과 같습니다space_num0.088space_mib=${space#* }space_mibMiBprintf %12.2f

mtr                         0.09 MiB
  pkgconfig                 0.62 MiB
    libiconv                6.27 MiB
      gperf                 0.00 MiB
  glib2                    46.09 MiB
    xz                      1.68 MiB
      gettext              24.83 MiB
        expat               1.11 MiB
        ncurses            15.17 MiB
    libxml2                10.40 MiB
      zlib                  0.72 MiB
    libffi                  0.14 MiB
    pcre                    5.95 MiB
      bzip2                 0.65 MiB
      libedit               0.80 MiB

0.088 MiB반올림이 되니 참고하세요0.09 MiB

또한 실제로 계산할 필요가 없도록 space_mib항상 로 설정되어 있다는 점에 유의하세요.MiB

port rdeps mtr 2>/dev/null | sed -E "1 s/.*of (.*) @.*/\1/" |
     while IFS= read -r line
     do
         space_num="$(port space --units MiB --total $line 2>/dev/null | cut -d ' ' -f 1)"
         printf "%-20s%12.2f %s\n" "$line" "$space_num" "MiB"
     done

같은 상기와.

잘림 포함

단순히 숫자를 자르려면 숫자보다는 문자열로 처리하는 것이 좋습니다. 이 명령

port rdeps mtr 2>/dev/null | sed -E "1 s/.*of (.*) @.*/\1/" |
     while IFS= read -r line
     do
         printf "%-30s%s\n" "$line" \
                  "$(port space --units MiB --total $line 2>/dev/null | cut -d ' ' -f 1-2)"
     done | sed -E -e 's/(\..*) /\100 /' -e 's/(.{25}) *(....\...).*( .*)/\1\2\3/'

이전 답변과 거의 동일하게 시작됩니다. 그러나 다음은 sed두 부분으로 구성된 파이프를 통해 모든 것을 파이프합니다 .

  • s/(\..*) /\100 /
    이는 소수점( \.)과 그 뒤의 모든 문자( .*)와 일치하며 공백 문자는 포함하지 않습니다. 그런 다음 일치하는 문자열 전체를 공백( ) 앞의 부분 \1, 두 개의 0 및 공백으로 바꿉니다. (라고 말할 수도 있지만 s/(\..*)( )/\100\2/동일한 작업을 수행했을 것입니다.) 이는 및 0.088 MiB로 변경 됩니다 0.08800 MiB. 데이터에 있는 경우 로 변경됩니다. 그러나 뒤에 숫자가 없더라도 모든 숫자에 소수점이 있다고 가정합니다. (또한 문자열, , 등에는 마침표가 없다고 가정합니다.)0.0 MiB0.000 MiB42. MiB42.00 MiBmtrpkgconfiglibiconv

    우리는 이를 보장하기 위해 이를 수행해야 합니다.각 숫자에는 소수점 이하 두 자리 이상이 있습니다. gperf이 수정을 하기 전에는 그렇지 않았습니다.

  • s/(.{25}) *(....\...).*( .*)/\1\2\3/
    .{25}.........................의 약어이며 임의의 25자입니다. 이 정도면 가장 길고(예: libiconv) 가장 깊게 들여쓰기된 문자열을 캡처할 수 있을 만큼 긴 것 같습니다. 그런 다음 임의의 문자( .*), 실제로는 단지 공백 묶음이기를 바랍니다. 그런 다음 ....\...4개의 문자, 소수점 및 2개의 문자를 더 일치시킵니다. 공백 수가 을 초과하는 경우 9999소수점 왼쪽 4자리 이상 일치하도록 변경해야 합니다. 그런 다음 원하는 수의 문자( .*), 즉 소수점 뒤 처음 두 자리 뒤의 모든 숫자입니다. 그런 다음 공백과 나머지 줄 ( ( .*))을 바랍니다  MiB. 그런 다음 조각을 문자열(적절한 선행 및 후속 공백 포함), 숫자(충분한 선행 공백 포함)로 다시 조립합니다..) \2, 단위가 이어집니다.

이 명령의 출력은 다음과 같습니다.

mtr                         0.08 MiB
  pkgconfig                 0.61 MiB
    libiconv                6.27 MiB
      gperf                 0.00 MiB
  glib2                    46.09 MiB
    xz                      1.67 MiB
      gettext              24.82 MiB
        expat               1.10 MiB
        ncurses            15.17 MiB
    libxml2                10.40 MiB
      zlib                  0.72 MiB
    libffi                  0.14 MiB
    pcre                    5.95 MiB
      bzip2                 0.64 MiB
      libedit               0.79 MiB

0.088 MiB로 잘 립니다 0.08 MiB.

물론, 원하는 경우 위의 복합 명령을 모두 한 줄에 넣을 수 있으며 필요에 맞게 너비 상수( 12, 20, 등) 25를 조정해야 합니다.30

답변2

아시다시피 printf이는 인쇄물의 서식을 지정하는 데 훌륭한 도구입니다. 이미 배웠듯이 %s이는 출력 문자열의 형식입니다.  %20s오른쪽 정렬되고 왼쪽이 공백으로 채워진(필요한 경우) 20자 길이의 문자열을 출력합니다.  %-20s반대의 경우도 마찬가지입니다. 20자 길이의 문자열을 출력하고 왼쪽 정렬되고 오른쪽은 공백으로 채워집니다(필요한 경우). 예를 들어 다음 명령은

printf "%-20s%s\n" "mtr" "0.088 MiB"
printf "%-20s%s\n" "  pkgconfig" "0.615 MiB"
printf "%-20s%s\n" "    libiconv" "6.270 MiB"

출력을 생성합니다

mtr                 0.088 MiB
  pkgconfig         0.615 MiB
    libiconv        6.270 MiB

따라서 다음 명령을 사용하여 원하는 결과를 얻을 수 있습니다.

port rdeps mtr 2>/dev/null | sed -E "1 s/.*of (.*) @.*/\1/" |
     while IFS= read -r line
     do
         printf "%-20s%s\n" "$line" \
                  "$(port space --units MiB --total $line 2>/dev/null | cut -d ' ' -f 1-2)"
     done

$나는 타당한 이유가 없는 한 쉘 명령과 스크립트에서 참조(예: 변수)를 항상 인용해야 한다고 종종 권장합니다 . $(…)표현을 따옴표로 묶었습니다 . 그러나 $line선행 공백이 포함되어 있으므로

port space --units MiB --total "$line"

작동하지 않습니다.

물론 원한다면 위의 복합 명령을 모두 한 줄에 넣을 수 있으며 20필요에 맞게 조정해야 합니다.

관련 정보