왼쪽의 계층 구조를 가장 잘 유지하고 오른쪽의 크기 값을 정렬하려면 어떻게 해야 합니까?
또한 동시에 크기를 한 자리 또는 두 자리로 반올림하고 싶습니다.
시도해 보았지만 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_num
0.088
space_mib=${space#* }
space_mib
MiB
printf
%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 MiB
0.000 MiB
42. MiB
42.00 MiB
mtr
pkgconfig
libiconv
우리는 이를 보장하기 위해 이를 수행해야 합니다.예각 숫자에는 소수점 이하 두 자리 이상이 있습니다.
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
필요에 맞게 조정해야 합니다.