I am following this link https://stackoverflow.com/a/54599800/10220825
file.txt
Iteration 1
RAM: +2s
Cache: +142ms (total +417ms)
Iteration 2
RAM: +184ms
Cache: +172ms
Searchms: +131ms (total +385ms)
Iteration 3
RAM: +149ms
Searchms: +3.2s
I want to remove the ms or s
from the time value but not from name (example it should not remove Searchms to Search). Also I want to convert s into ms
by multiply into 1000
if the time value contains s
and print result accordingly.
Expected Output:
RAM: 2000 184 149
Cache: 142 172
Searchms: 131 3200
try.awk
/:/{vals[$1]=vals[$1] OFS $2+0}
END {
for (key in vals)
print key vals[key]
}
On executing : awk -f try.awk file.txt
Code Output:
Cache: 142 172
Searchms: 131 3.2
RAM: 2 184 149
In my output s is not converting to ms.
Please suggest me how I modify above source code try.awk
to convert s to ms.
New Test Case:
file.txt
Iteration 1
RAM: +2s342ms
Iteration 2
RAM: +2s
Iteration 3
RAM: +149ms
Code:
/:/ && $2 ~/ms$/{vals[$1]=vals[$1] OFS $2+0;next}
/:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000}
END {
for (key in vals)
print key vals[key]
}
Expected output:
RAM: 2342 2000 149
Output:
RAM: 2 2000 149
You can use the following awk
script:
/:/ && $2 ~/ms$/{vals[$1]=vals[$1] OFS $2+0;next}
/:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000}
END {
for (key in vals)
print key vals[key]
}
This will produce the output:
awk -f try.awk file.txt
Cache: 142 172
Searchms: 131 3200
RAM: 2000 184 149
Explanations:
- The condition
$2 ~/ms$/
will check if we have a line with ms
in this case the same logic is done as before and the next
will force awk
to jump to the next line.
/:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000}
when we reach this scope we know that we have a line with units in s
and we multiply it by 1000 to convert it to ms
.
To answer to your new requirements, I have adapted the try.awk
into:
/:/ && $2 ~/[0-9]+s[0-9]+ms$/{split($2,buff,/s/);vals[$1]=vals[$1] OFS (buff[1]+0)*1000+buff[2];next}
/:/ && $2 ~/ms$/{vals[$1]=vals[$1] OFS $2+0;next}
/:/ && $2 ~/[^m]s$/{vals[$1]=vals[$1] OFS ($2+0)*1000}
END {
for (key in vals)
print key vals[key]
}
Input:
$ cat file2.txt
Iteration 1
RAM: +2s342ms
Iteration 2
RAM: +2s
Iteration 3
RAM: +149ms
Output:
$ awk -f try.awk file2.txt
RAM: 2342 2000 149
A small adaptation of the OP:
/:/{ vals[$1]=vals[$1] OFS $2*($2~/ms$/ ? 1 : 1000 ) }
END { for (key in vals) print key vals[key] }
Remark: this will not work on all versions of awk, this makes use of the following nifty feature of gawk (and POSIX):
A string is converted to a number by interpreting any numeric prefix of the string as numerals: "2.5" converts to 2.5, "1e3" converts to 1,000, and "25fix" has a numeric value of 25. Strings that can’t be interpreted as valid numbers convert to zero.
source: Gnu Awk manual: Conversion of Strings and Numbers
This behaviour is Posix valid and works using the C-function atof
. POSIX, however, gives a second option to convert strings to numbers where "25fix" would convert to 0. This is, for example, the case on Oracle:
Linux: GNU $ awk 'BEGIN{print "25fix"+0}'
25
SUN OS: SUNWesu $ /usr/bin/awk 'BEGIN{print "25fix"+0}'
0
SUN OS: SUNWxpg $ /usr/xpg4/bin/awk 'BEGIN{print "25fix"+0}'
25