1

我有 100 个数据文件,每个有 1000 行,它们看起来都像这样:

0       0   0   0
1       0   1   0
2       0   1   -1
3       0   1   -2
4       1   1   -2
5       1   1   -3
6       1   0   -3
7       2   0   -3
8       2   0   -4
9       3   0   -4
10      4   0   -4
.
.
.
999     1   47  -21
1000        2   47  -21

我开发了一个脚本,它应该取第 2、3、4 列中每个值的平方,然后对它们求和并求平方根。像这样:

temp = ($t1*$t1) + ($t2*$t2) + ($t3*$t3)
calc = $calc + sqrt ($temp)

然后计算该值的平方,并对每个数据文件中的这些数字进行平均,以输出每行的平均“calc”和每行的平均“fluc”。

这些数字的含义是这样的:第一个数字是步数,接下来的三个分别是x、y和z轴上的坐标。我试图找出“步骤”从原点带我的距离,这是用公式计算的r = sqrt(x^2 + y^2 + z^2)。接下来我需要 r 的波动,计算为f = r^4f = (r^2)^2。这些必须是 100 个数据文件的平均值,这导致我:

r = r + sqrt(x^2 + y^2 + z^2)
avg = r/s

同样对于 f ,其中 s 是我计算出使用的读取数据文件的数量sum=$(ls -l *.data | wc -l)。最后,我的最后一个计算是期望值r和平均值之间的偏差r,它是stddev = sqrt(fluc - (r^2)^2)在循环外使用最终值计算的。

我创建的脚本是:

#!/bin/bash

sum=$(ls -l *.data | wc -l)
paste -d"\t" *.data | nawk -v s="$sum" '{
    for(i=0;i<=s-1;i++)
    {
        t1 = 2+(i*4)
        t2 = 3+(i*4)
        t3 = 4+(i*4)
        temp = ($t1*$t1) + ($t2*$t2) + ($t3*$t3)
        calc = $calc + sqrt ($temp)
        fluc = $fluc + ($calc*$calc)
    }
    stddev = sqrt(($calc^2) - ($fluc))
    print $1" "calc/s" "fluc/s" "stddev
    temp=0
    calc=0
    stddev=0
}'

不幸的是,中途我收到一个错误:

nawk: cmd. line:9: (FILENAME=- FNR=3) fatal: attempt to access field -1

我对 awk 的经验不足,无法准确找出我哪里出错了,有人能指出我正确的方向或给我一个更好的脚本吗?

预期的输出是一个文件,其中包含:

0 0 0 0
1 (calc for all 1's) (fluc for all 1's) (stddev for all 1's)
2 (calc for all 2's) (fluc for all 2's) (stddev for all 2's)
.
.
.
4

2 回答 2

3

下面的脚本应该做你想做的事。唯一可能不起作用的是分隔符的选择。在您的原始脚本中,您似乎有标签。我的解决方案假设有空格。但改变这一点应该不是问题。

它只是将所有文件按顺序传输到 中,nawk而不首先计算文件。我知道这不是必需的。它不是试图跟踪文件中的位置,而是使用数组来存储每个步骤的单独统计数据。最后,它遍历找到的所有步骤索引并输出它们。由于迭代没有排序,有另一个管道进入sort处理这个问题的 Unix 调用。

#!/bin/bash
# pipe the data of all files into the nawk processor
cat *.data | nawk ' 
BEGIN { 
  FS=" "                         # set the delimiter for the columns
} 
{
  step = $1                      # step is in column 1
  temp = $2*$2 + $3*$3 + $4*$4

  # use arrays indexed by step to store data
  calc[step] = calc[step] + sqrt (temp)
  fluc[step] = fluc[step] + calc[step]*calc[step]
  count[step] = count[step] + 1   # count the number of samples seen for a step
}
END {
  # iterate over all existing steps (this is not sorted!)
  for (i in count) {
    stddev = sqrt((calc[i] * calc[i]) + (fluc[i] * fluc[i]))
    print i" "calc[i]/count[i]" "fluc[i]/count[i]" "stddev
  }
}' | sort -n -k 1 # that' why we sort here: first column "-k 1" and numerically "-n"

编辑

正如@edmorton 所建议的那样,awk可以自行加载文件。以下增强版本删除了对 的调用cat,而是将文件模式作为参数传递给nawk. 此外,正如@NictraSavios 所建议的那样,新版本引入了对最后一步统计输出的特殊处理。请注意,统计信息的收集仍然针对所有步骤完成。在读取数据的过程中抑制这一点有点困难,因为那时我们还不知道最后一步是什么。虽然这可以通过一些额外的努力来完成,但您可能会失去很多数据处理的稳健性,因为现在脚本不对以下内容做出任何假设:

  • 提供的文件数量,
  • 处理文件的顺序,
  • 每个文件中的步骤数,
  • 文件中步骤的顺序,
  • 步骤的完整性作为没有“漏洞”的范围。

增强脚本:

#!/bin/bash
nawk ' 
BEGIN { 
  FS=" "   # set the delimiter for the columns (not really required for space which is the default)
  maxstep = -1
} 
{
  step = $1                      # step is in column 1
  temp = $2*$2 + $3*$3 + $4*$4

  # remember maximum step for selected output
  if (step > maxstep)
    maxstep = step

  # use arrays indexed by step to store data
  calc[step] = calc[step] + sqrt (temp)
  fluc[step] = fluc[step] + calc[step]*calc[step]
  count[step] = count[step] + 1   # count the number of samples seen for a step
}
END {
  # iterate over all existing steps (this is not sorted!)
  for (i in count) {
    stddev = sqrt((calc[i] * calc[i]) + (fluc[i] * fluc[i]))
    if (i == maxstep)
      # handle the last step in a special way
      print i" "calc[i]/count[i]" "fluc[i]/count[i]" "stddev
    else
      # this is the normal handling
      print i" "calc[i]/count[i]
  }
}' *.data | sort -n -k 1 # that' why we sort here: first column "-k 1" and numerically "-n"
于 2013-12-01T01:22:04.960 回答
1

您还可以使用:

awk -f c.awk *.data

c.awk在哪里

{
    j=FNR
    temp=$2*$2+$3*$3+$4*$4
    calc[j]=calc[j]+sqrt(temp)
    fluc[j]=fluc[j]+calc[j]*calc[j]
}

END {
    N=ARGIND
    for (i=1; i<=FNR; i++) {
        stdev=sqrt(fluc[i]-calc[i]*calc[i])
        print i-1,calc[i]/N,fluc[i]/N,stdev
    }
}
于 2013-12-01T06:47:57.820 回答