[英]AWK matching values in a column and performing calculation
我是AWK的新手,我正試圖找出問題的答案。 我有一個包含以下值的平面文件:
403 | SanMateo | f | 2015-04-09 18:50:24.38
403 | SanMateo | t | 2015-04-09 18:45:24.36
403 | SanMateo | t | 2015-04-09 18:40:24.383
403 | SanMateo | f | 2015-04-09 18:35:24.357
403 | SanMateo | t | 2015-04-09 18:30:24.355
404 | RedwoodCity| f | 2015-04-09 18:35:50.308
404 | RedwoodCity| t | 2015-04-09 18:30:50.242
404 | RedwoodCity| f | 2015-04-09 18:25:50.245
404 | RedwoodCity| t | 2015-04-09 18:20:50.242
404 | RedwoodCity| f | 2015-04-09 18:15:50.242
我想使用awk將當前行的$ 1與下一行的$ 1進行比較,並且$ 3~ / f /。 如果該語句為真,則從當前行的$ 4中減去下一行的$ 4,並將差值寫入當前行的新列中,如果為false則不執行任何操作。 到目前為止我所擁有的是:
awk 'BEGIN {FS="|";} {if (NR $1 ~ NR++ $1 && $3 ~ /f/) subtract = NR $4 - NR++ $4; {print subtract}}' allHealthRecords_Sorted
顯然這不起作用。 有人可以幫忙嗎?
將其保存為time_diff.awk
BEGIN {FS = "[[:blank:]]*\\|[[:blank:]]*"}
# convert "YYYY-mm-dd HH:MM:SS.fff" to a number
function to_time(timestamp, fraction) {
fraction = timestamp
sub(/\..*$/, "", timestamp)
gsub(/[-:]/, " ", timestamp)
sub(/.*\./, "0.", fraction)
return mktime(timestamp) + fraction
}
# gawk has no builtin abs() function
function abs(val) {
return( val < 0 ? -1*val : val)
}
# add the time diff if the condition is met
NR > 1 {
diff = 0
if ($1+0 == key && flag == "f")
diff = abs( to_time($4) - to_time(time) )
print line (diff > 0 ? " | " diff : "")
}
{
# remember the previous line's values
key = $1+0; flag = $3; time = $4; line = $0
}
END {print}
然后
$ gawk -f time_diff.awk file
403 | SanMateo| f | 2015-04-09 18:50:24.38 | 300.02
403 | SanMateo| t | 2015-04-09 18:45:24.36
403 | SanMateo| t | 2015-04-09 18:40:24.383
403 | SanMateo| f | 2015-04-09 18:35:24.357 | 300.002
403 | SanMateo| t | 2015-04-09 18:30:24.355
404 | RedwoodCity| f | 2015-04-09 18:35:50.308 | 300.066
404 | RedwoodCity| t | 2015-04-09 18:30:50.242
404 | RedwoodCity| f | 2015-04-09 18:25:50.245 | 300.003
404 | RedwoodCity| t | 2015-04-09 18:20:50.242
404 | RedwoodCity| f | 2015-04-09 18:15:50.242
你沒有顯示你的預期輸出,所以我們無法測試它,4美元是一個日期,所以idk你的意思是“減去”,但這基本上是正確的方法:
$ cat tst.awk
BEGIN{ FS="[[:space:]]*[|][[:space:]]*"; OFS=" | " }
split(prev,p) { print prev ( ($1==p[1])&&(p[3]=="f") ? OFS p[4] - $4 : "") }
{ prev = $0 }
END { print prev ( ($1==p[1])&&(p[3]=="f") ? OFS p[4] - $4 : "") }
$ awk -f tst.awk file
403 | SanMateo | f | 2015-04-09 18:50:24.38 | 0
403 | SanMateo | t | 2015-04-09 18:45:24.36
403 | SanMateo | t | 2015-04-09 18:40:24.383
403 | SanMateo | f | 2015-04-09 18:35:24.357 | 0
403 | SanMateo | t | 2015-04-09 18:30:24.355
404 | RedwoodCity| f | 2015-04-09 18:35:50.308 | 0
404 | RedwoodCity| t | 2015-04-09 18:30:50.242
404 | RedwoodCity| f | 2015-04-09 18:25:50.245 | 0
404 | RedwoodCity| t | 2015-04-09 18:20:50.242
404 | RedwoodCity| f | 2015-04-09 18:15:50.242
即你有1行的緩沖區,所以你總是在操作並輸出你讀過的前一行。
在BEGIN操作中,使用getline
讀取第一行並保存$ 1和$ 4的值。
在此后的每一行上,將$ 1與上一行的保存值進行比較。 如果它們相同,並且$3 ~ /f/
,則執行所需的過程。 然后為下一行保存$ 1和$ 4的值。
這應該足以讓你開始。 如果您在編寫代碼時遇到問題,請回過頭來提出更多問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.