Phân tích cú pháp tiện dụng cho các số có hậu tố đơn vị?


10

Giả sử bạn có dữ liệu với số lượng ở định dạng có thể đọc được, chẳng hạn như đầu ra du -hvà muốn hoạt động thêm trên các số đó. Giả sử bạn muốn chuyển dữ liệu của mình qua grep để thực hiện tổng hợp một tập hợp con của dữ liệu đó. Bạn thực hiện quảng cáo này trên nhiều hệ thống mà bạn chưa từng thấy trước đây và chỉ có các tiện ích tối thiểu. Bạn muốn chuyển đổi hậu tố cho tất cả các hậu tố 10 ^ n tiêu chuẩn.

Có tồn tại tiện ích gnu-linux để chuyển đổi các số có hậu tố thành số thực trong một đường ống dẫn không? Bạn có một hàm bash được viết để làm điều này, hoặc một số perl có thể dễ nhớ, thay vì độ dài của các thay thế regex hoặc một vài bước sed?

38M     /var/crazyface/courses/200909-90147
2.7M    /var/crazyface/courses/200909-90157
1.1M    /var/crazyface/courses/200909-90159
385M    /var/crazyface/courses/200909-90161
1.3M    /var/crazyface/courses/200909-90169
376M    /var/crazyface/courses/200907-90171
8.0K    /var/crazyface/courses/200907-90173
668K    /var/crazyface/courses/200907-90175
564M    /var/crazyface/courses/200907-90178
4.0K    /var/crazyface/courses/200907-90179

| grep 200907 | <amazing suffix conversion> | awk '{s+=$1} END {print s}'


Tài liệu tham khảo có liên quan:


2
Bạn hiếm khi cần sử dụng grep và awk. Nếu bạn đang sử dụng awk, thì hãy sử dụng awk. Chỉ cần thêm /200907/vào trước mã mỗi dòng của bạn, ví dụ:awk '/200907/{s+=$1} END {print s}'
Tony

Câu trả lời:


14

Dựa trên câu trả lời của tôi tại một trong những câu hỏi bạn liên kết đến:

awk '{
    ex = index("KMGTPEZY", substr($1, length($1)))
    val = substr($1, 0, length($1) - 1)

    prod = val * 10^(ex * 3)

    sum += prod
}
END {print sum}'

Một phương pháp khác được sử dụng:

sed 's/G/ * 1000 M/;s/M/ * 1000 K/;s/K/ * 1000/; s/$/ +\\/; $a0' | bc

đối với phương thức thứ hai, nếu hậu tố là s thì sao?
djuarez

@djuarez: Số nhân của s là gì?
Tạm dừng cho đến khi có thông báo mới.

Không, chỉ ngoại suy trên các trường hợp đơn vị khác.
djuarez

@djuarez: Điều đó không có nghĩa gì cả. Câu trả lời này là về hậu tố SI, không phải đơn vị chung (giây, có lẽ?). Để mở rộng sedlệnh trong câu trả lời của tôi, bạn sẽ thêm các mệnh đề để xử lý các hậu tố SI bổ sung như tôi hiển thị trong awklệnh. s/T/ * 1000 G;được thêm vào lúc đầu sẽ thêm terabyte chẳng hạn.
Tạm dừng cho đến khi có thông báo mới.

3

Bạn có thể sử dụng biểu thức chính quy perl để làm điều này. Ví dụ,

$value = 0;
if($line =~ /(\d+\.?\d*)(\D+)\s+/) {
   $amplifier = 1024 if ($2 eq 'K');
   $amplifier = 1024 * 1024 if ($2 eq 'M');
   $amplifier = 1024 * 1024 * 1024 if ($2 eq 'G');
   $value = $1 * $amplifier;
}

Đây là một kịch bản đơn giản. Bạn có thể coi nó là điểm khởi đầu. Hy vọng nó sẽ giúp!


Thật vậy, đây là một cách. Tôi cũng đã tìm thấy stackoverflow.com/questions/2557649/ .
đậu

3

Cá nhân, tôi chỉ không sử dụng cờ -h ở vị trí đầu tiên. Phiên bản "con người có thể đọc được" làm tròn số sẽ cần được làm tròn lại khi bạn chuyển đổi trở lại, thậm chí còn kém chính xác hơn. (Ví dụ: 2,7MiB là 2831155,2 byte. Bạn đã làm gì với 0,8 byte còn lại ??!)

Mặt khác, bạn có thể yêu cầu unitschuyển đổi MiB / GiB / KiB thành "B" và nó sẽ xử lý việc này, nhưng bạn phải làm một cái gì đó như (giả sử đầu ra của bạn được gắn thẻ, nếu không thì cutthích hợp)

{your output} | cut -f1 '-d{tab}' | xargs -L 1 -I {} units -1t {}iB B | awk '{s+=$1}END{printf "%d\n",s}'

Cũng lưu ý rằng có một sự mất chính xác. Bổ sung đầu vào cho các đơn vị cũng hoạt động .. nhưng tôi thấy unitsthiếu trên bản phân phối tối thiểu của mình! Tôi nghĩ rằng tất cả chúng ta sẽ làm điều này khác đi nếu chúng ta có toàn quyền kiểm soát mọi thứ.
đậu

2
VALUE=$1

for i in "g G m M k K"; do
        VALUE=${VALUE//[gG]/*1024m}
        VALUE=${VALUE//[mM]/*1024k}
        VALUE=${VALUE//[kK]/*1024}
done

[ ${VALUE//\*/} -gt 0 ] && echo VALUE=$((VALUE)) || echo "ERROR: size invalid, pls enter correct size"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.