以下对第12列中的数据非常有用,但我有70多个列并不完全相同,我需要输出所有列,转换后的列替换科学值。
awk -F',' '{printf "%.41f\n", $12}' $file
由于
这是一行......
2012-07-01T21:59:50,2012-07-01T21:59:00,1817,22901,264,283,549,1,2012-06-24T13:20:00,2.600000000000000e+001,4.152327506554059e+001,-7.893523806678388e+001,5.447572631835938e+002,2.093000000000000e+003,5.295000000000000e+003,1,194733,1.647400093078613e+001,31047680,1152540,29895140,4738,1.586914062500000e+000,-1.150000000000000e+002,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,3.606000000000000e+003,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,4.557073364257813e+002,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,11,0.000000000000000e+000,2.000000000000000e+000,0,0,0,0,4.466836981009692e-004,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,8,0,840,1,600,1,6,1,1,1,5,2,2,2,1,1,1,1,4854347,0,-
更新
这适用于非转换输出。出于某种原因,我在插入else if语句时遇到了一些麻烦。一切似乎都在文件或cli上给我一个语法错误。
awk -F',' '{for (i=1;i<=NF;i++) {if (i <= 9||i == 16||i == 17||i == 19||i == 20||i == 21||i == 22|| i == 40|| i == 43||i == 44||i == 45||i == 46||i >= 51) printf ($i",")};}' $file
我想在上面的代码中插入以下语句??
else if (i == 10) printf ("%.41f", $i)
解决
搞定了。感谢所有伟大的想法。我似乎无法使用awk -f在文件中工作,但在命令行上这很有用。我把这个班轮放在我的程序中。
awk -F',' '{for (i=1;i<=NF;i++) {if (i <= 9||i == 16||i == 17||i >= 19&&i <= 22|| i == 40|| i >= 43&&i <= 46||i >= 51&&i <= 70) printf($i","); else if (i == 10||i == 18) printf("%.2f,", $i); else if (i == 11||i == 12) printf("%.41f,", $i); else if (i == 13) printf("%.1f,", $i); else if (i == 14||i == 15||i >= 24&&i <= 46) printf ("%d,", $i); else if (i == 23) printf("%.4f,", $i); else if (i >= 47&&i <= 50) printf("%.6f,", $i); if (i == 71) printf ($i"\n")};}'
RESULT
2012-07-01T21:59:50,2012-07-01T21:59:00,1817,22901,264,283,549,1,2012-06-24T13:20:00,26.00,41.52327506554058800247730687260627746582031,-78.93523806678388154978165403008460998535156,544.8,2093,5295,1,194733,16.47,31047680,1152540,29895140,4738,1.5869,-115,0,0,0,0,0,0,0,3606,0,0,0,455,0,0,0,11,0,2,0,0,0,0,0.000447,0.000000,0.000000,0.000000,8,0,840,1,600,1,6,1,1,1,5,2,2,2,1,1,1,1,4854347,0,-
答案 0 :(得分:3)
您可以在循环中进行正则表达式匹配,以选择每个字段的格式,因为数字也是AWK中的字符串:
#!/usr/bin/awk -f
BEGIN {
d = "[[:digit:]]"
OFS = FS = ","
}
{
delim = ""
for (i = 1; i <= NF; i++) {
if ($i ~ d "e+" d d d "$") {
printf "%s%.41f", delim, $i
}
else {
printf "%s%s", delim, $i
}
delim = OFS
}
printf "\n"
}
修改强>
我已经更改了上面的版本,因此您可以看到它将如何在文件中用作AWK脚本。保存它(我称之为“scinote”)并将其设置为可执行文件chmod u+x scinote
,然后您可以像这样运行它:./scinote inputfile
我还修改了你在问题中添加的最新版本,使其更简单一些,所以它已准备好进入上面的脚本文件。
#!/usr/bin/awk -f
BEGIN {
plainlist = "16 17 19 20 21 22 40 43 44 45 46"
split(plainlist, arr)
for (i in arr) {
plainfmt[arr[i]] = "%s"
}
OFS = FS = ","
}
{
delim = ""
for (i = 1; i <= NF; i++) {
printf "%s", delim
if (i <= 9 || i in plainfmt || i >= 51) {
printf plainfmt[i], $i
}
else if (i == 10) {
printf "%.41f", $i
}
else if (i == 12) {
printf "%.12f", $i
}
delim = OFS
}
printf "\n"
}
如果您有更多字段包含其他格式(而不是每个格式一个),您可以执行与plainfmt
数组类似的操作。
答案 1 :(得分:0)
您可以随时遍历所有数据字段,并在printf
中使用它们。对于一个简单的文件只是为了测试机制,你可以试试这个:
awk '{for (i=1; i<=NF; i++) printf("%d = %s\n", i, $i);}' data.txt
请注意,此处未设置-F
,因此字段将按空格分割。
NF
是一行中字段数量的预定义变量,字段以1开头(例如,$1
,$2
等,直到$NF
)。 $0
就是整行。
因此,对于您的示例,这可能有效:
awk -F',' '{for (i=1; i<=NF; i++) printf "%.41f\n", $i}' $file
更新 基于以下评论(不是系统测试语法):
如果某些字段需要区别对待,则可能需要使用switch语句或if-statement来区别对待不同的字段。如果您将脚本存储在一个文件中,让我们称之为so.awk
并像这样调用它,这会更容易:
awk -f so.awk $file
您的脚本可能包含以下内容:
BEGIN{ FS=',' }
{ for (i=1; i<=NF; i++)
{
if (i == 20 || i == 22|| i == 30)
printf( " .. ", $i)
else if ( i == 13 || i == 24)
printf( " ....", $i)
etc.
}
}
您当然也可以使用if (i > 2) ...
或其他范围,以避免在可能的情况下列出每个字段。
作为这一系列if语句的替代方法,请参阅上面提到的switch语句。