我有一個檔案,其中包含有關日常存盤利用率的一些資訊。有兩列 - DD.MM 日期和每天以 KB 為單位的使用情況。
隨著存盤使用量的增加,我使用 awk 來顯示每隔一行與前一行之間的差異(以 GB 為單位)。
示例檔案:
20.09 10485760
21.09 20971520
22.09 26214400
23.09 27262976
我的 awk 命令:
awk 'NR > 1 {a=($2-prev)/1024^2" GB"} {prev=$2} {print $1,$2,a}' file
這輸出:
20.09 10485760
21.09 20971520 10 GB
22.09 26214400 5 GB
23.09 27262976 1 GB
我還想在第一列之前添加作業日名稱。檔案中的日期格式始終為 DD.MM,因此,為了讓 GNU 日期接受它作為有效輸入并回傳作業日名稱,我撰寫了這個管道:
echo '20.09.2022' | awk -v FS=. -v OFS=- '{print $3,$2,$1}' | date -f - %a
它可以作業,但我想從第一個 awk 中為每個已處理的行呼叫它,并將第一列日期作為引數并附加“ .2022 ”以便作業,并放置這個外部管道的輸出(它將是作業日名稱)在第一列中的日期之前。
示例輸出:
Tue 20.09 10485760
Wed 21.09 20971520 10 GB
Thu 22.09 26214400 5 GB
Fri 23.09 27262976 1 GB
我查看了system()awk 中的選項,但無法使其與我的管道和我的第一個 awk 命令一起使用。
uj5u.com熱心網友回復:
第一種解決方案:使用getlineinawk請嘗試以下解決方案。
awk '
NR>1{
a=($2-prev)/1024^2" GB"
}
{
split($1,arr,".")
value="2022-"arr[2]"-"arr[1]
dateVal="date -d \"" value "\" %a"
newVal = ( (dateVal | getline line) > 0 ? line : "N/A" )
close(dateVal)
print newVal,$0,a
prev=$2
}
' Input_file
第二種解決方案:使用您顯示的示例,請嘗試以下awk代碼。system命令的作用是awk:它在一個單獨的 shell 中運行提到的命令,所以基本上你正在呼叫awk-->system-->shell-->commands所以盡管如此,你只需要在awk所有日子里用 1 獲取所有值(基于你的第一個欄位Input_file),我們可以將它作為輸入傳遞給另一個awk我們正在進行實際空間計算的地方,我們可以合并它們(因為system命令通過 shell 命令列印輸出,所以我們不能將該輸出與awk輸出合并)。我們也可以使用 while 回圈來完成,但恕我直言,這樣做awk可能會更快。
awk '
FNR==NR{
arr[FNR]=$0
next
}
NR>1{
a=($2-prev)/1024^2" GB"
}
{
print arr[FNR],$1,$2,a
prev=$2
}
' <(awk '{split($1,arr,".");system("d=\"2022-" arr[2]"-"arr[1]"\";date -d \"$d\" %a")}' Input_file) Input_file
顯示樣本的輸出如下:
Tue 20.09 10485760
Wed 21.09 20971520 10 GB
Thu 22.09 26214400 5 GB
Fri 23.09 27262976 1 GB
uj5u.com熱心網友回復:
既然你有 GNU 日期,你還應該有 GNU awk,它具有內置的時間函式,這將比 awk 產生一個子shell 來呼叫date每個輸入行快幾個數量級:
$ cat tst.sh
#!/usr/bin/env bash
awk '
BEGIN {
year = strftime("%Y")
}
NR > 1 {
diff = ( ($2 - prev) / (1024 ^ 2) ) " GB"
}
{
split($1,dayMth,/[.]/)
secs = mktime(year " " dayMth[2] " " dayMth[1] " 12 0 0")
day = strftime("%a",secs)
print day, $0, diff
prev = $2
}
' "${@:--}"
$ ./tst.sh file
Tue 20.09 10485760
Wed 21.09 20971520 10 GB
Thu 22.09 26214400 5 GB
Fri 23.09 27262976 1 GB
如果由于某種原因您沒有 GNU awk并且無法獲得它,那么使用 GNU date 和任何 awk,這種 2-pass 方法將相當有效地作業:
$ cat tst.sh
#!/usr/bin/env bash
awk -v year="$(date '%Y')" -v OFS='-' '{
split($1,dayMth,/[.]/)
print year, dayMth[2], dayMth[1]
}' "$@" |
date -f- '%a' |
awk '
NR == FNR {
days[NR] = $1
next
}
FNR > 1 {
diff = ( ($2 - prev) / (1024 ^ 2) ) " GB"
}
{
print days[FNR], $0, diff
prev = $2
}
' - "$@"
$ ./tst.sh file
Tue 20.09 10485760
Wed 21.09 20971520 10 GB
Thu 22.09 26214400 5 GB
Fri 23.09 27262976 1 GB
第二個腳本的缺點是它無法從流中讀取輸入,只能從檔案中讀取,因為它必須讀取兩次。如果這是一個問題,并且您的輸入不是太大而無法在磁盤上放置副本,那么您始終可以使用臨時檔案,例如:
$ cat tst.sh
#!/usr/bin/env bash
tmp=$(mktemp) &&
trap 'rm -f "$tmp"; exit' 0 &&
cat "${@:--}" > "$tmp" || exit 1
awk -v year="$(date '%Y')" -v OFS='-' '{
split($1,dayMth,/[.]/)
print year, dayMth[2], dayMth[1]
}' "$tmp" |
date -f- '%a' |
awk '
NR == FNR {
days[NR] = $1
next
}
FNR > 1 {
diff = ( ($2 - prev) / (1024 ^ 2) ) " GB"
}
{
print days[FNR], $0, diff
prev = $2
}
' - "$tmp"
$ ./tst.sh file
Tue 20.09 10485760
Wed 21.09 20971520 10 GB
Thu 22.09 26214400 5 GB
Fri 23.09 27262976 1 GB
uj5u.com熱心網友回復:
date可以處理多個換行符日期,因此我建議以下解決方案,讓file.txt內容
20.09 10485760
21.09 20971520 10 GB
22.09 26214400 5 GB
23.09 27262976 1 GB
然后
awk 'BEGIN{FS="[[:space:].]";OFS="-"}{print "2022",$2,$1}' file.txt | date -f - %a | paste -d ' ' - file.txt
給出輸出
Tue 20.09 10485760
Wed 21.09 20971520 10 GB
Thu 22.09 26214400 5 GB
Fri 23.09 27262976 1 GB
說明:我使用 GNUAWK提取和準備消費的日期date,所以20.09變成2022-09-20等等,然后date用于計算星期幾的代號,然后paste用于獲取由空格字符并排剪切的列,第 1 列-表示使用標準輸入,第二列不變file.txt
(在 GNU Awk 5.0.1 中測驗并粘貼(GNU coreutils)8.30)
uj5u.com熱心網友回復:
誰說你不能用system()得到作業日?
此功能還帶有自動
gnu-date與bsd-date檢測,(通過
gnu-date回傳到納秒精度的能力,這是bsd-date缺乏的),并相應地調整其呼叫語法
jot -w '2022-09-%d' 30 | gtail -n 12 | mawk 'function ____(_) { return \ substr("SunMonTueWedThuFriSat",(_=\ system("exit \140 date -" (\ system("exit \140date \"%s%6N"\ "\" |grep -cF N\140") ? "j -f " \ "\"%Y-%m-%d\"":"d") " \""(_) \ "\" %w \140")) _ _ (_^=_<_),_ _ _) } ($ NF=____($!_))^_'
2022-09-19 Mon
2022-09-20 Tue
2022-09-21 Wed
2022-09-22 Thu
2022-09-23 Fri
2022-09-24 Sat
2022-09-25 Sun
2022-09-26 Mon
2022-09-27 Tue
2022-09-28 Wed
2022-09-29 Thu
2022-09-30 Fri
system()如果您明確地將其退出代碼設定為您想要的任何值,通常可以回傳一個無符號整數 from 0to ,255
因此,只要所需的值范圍在256(或可以合并到其中)范圍內,就可以利用system()并比完整的getline例程更快地獲得結果。
但由于此解決方法需要回傳數值,因此無法直接使用內置格式化代碼date '%a'。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/510313.html
標籤:日期awk
