Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 将一系列矩阵文件转换为awk中的坐标索引_Bash_Awk - Fatal编程技术网

Bash 将一系列矩阵文件转换为awk中的坐标索引

Bash 将一系列矩阵文件转换为awk中的坐标索引,bash,awk,Bash,Awk,我有一个文件0000.vx.dat、0000.vy.dat、0000.vz.dat;的时间序列。。。;0077.vx.dat,0077.vy.dat,0077.vz.dat。。。每个文件都是一个空间分隔的二维矩阵。我希望将每个三元组文件合并成基于坐标的数据格式,即: [timestep+1][i][j][vx(i,j)][vy(i,j)][vz(i,j)] 每个文件编号对应一个特定的时间步长。考虑到我在这个时间序列中拥有的数据量(~4GB),bash并没有削减数据量,所以似乎是时候转向awk了。

我有一个文件0000.vx.dat、0000.vy.dat、0000.vz.dat;的时间序列。。。;0077.vx.dat,0077.vy.dat,0077.vz.dat。。。每个文件都是一个空间分隔的二维矩阵。我希望将每个三元组文件合并成基于坐标的数据格式,即:

[timestep+1][i][j][vx(i,j)][vy(i,j)][vz(i,j)]

每个文件编号对应一个特定的时间步长。考虑到我在这个时间序列中拥有的数据量(~4GB),bash并没有削减数据量,所以似乎是时候转向awk了。。。特别是令人作呕。在bash中尝试这个是相当愚蠢的,但这里是 我命运多舛的尝试:

for x in $(seq 1 78)
do
  tfx=${tf[$x]} # an array of padded zeros
  for y in $(seq 1 1568)
  do
    for z in $(seq 1 1344)
    do
      echo $x $y $z $(awk -v i=$z -v j=$y "FNR == i {print j}" $tfx.vx.dat) $(awk -v i=$z -v j=$y "FNR == i {print j}" $tfx.vy.dat) $(awk -v i=$z -v j=$y "FNR == i {print j}" $tfx.vz.dat) >> $file
    done
  done
done
编辑:谢谢你,ruakh,你指出我用shell变量格式保存了j,前面有一个$!这只是原始脚本的一个片段,但我想应该被认为是它的精髓

可以说,这将花费大约六个月的时间,因为bash中与O(MxN)算法、子shell和管道等相关的所有内存开销。我最多只能在一天内找到更多。每个文件大约有18MB,所以这应该不是什么大问题。我很乐意在awk中一次执行一个时间步,前提是每个时间步都有一个输出文件。我想,我可以把它们都放在一起,没有太多的后遗症。不过,重要的是,时间步长编号必须是坐标列表中的第一项。我可以通过bash例程中的awk-v参数(见上文)实现这一点。我不知道如何在三个单独的文件中查找矩阵的特定元素,并将它们全部放在一个输出中。这是我想克服的主要障碍。我希望mawk能在工作量和计算速度之间提供一个很好的平衡。如果这对于一个awk脚本来说似乎太多了,我可以去一些较低的级别,如果有人回答让我知道我应该去C,我将不胜感激

提前谢谢你!我很喜欢awk,但恐怕我是个新手

三个文件0000.vx.dat、0000.vy.dat和0000.vz.dat的内容如下(尺寸正确的大型文件除外):

0000.vx.dat:

1 2 3
4 5 6
7 8 9
0000.vy.dat:

10 11 12
13 14 15
16 17 18
0000.vz.dat:

19 20 21
22 23 24
25 26 27
我希望能够输入:

awk -v t=1 -f stackoverflow.awk 0000.vx.dat 0000.vy.dat 0000.vz.dat
并获得以下输出:

1 1 1 1 10 19
1 1 2 2 11 20
1 1 3 3 12 21
1 2 1 4 13 22
1 2 2 5 14 23
1 2 3 6 15 24
1 3 1 7 16 25
1 3 2 8 17 26
1 3 3 9 18 27

编辑:谢勒,谢谢你建议我把所需的输入和输出放得更清楚

我个人使用
gawk
处理大部分文本文件。但是,由于您已经请求了一个兼容
mawk
的解决方案,这里有一种方法可以解决您的问题。在当前工作目录中运行:

for i in *.vx.dat; do nawk -f script.awk "$i" "${i%%.*}.vy.dat" "${i%%.*}.vz.dat"; done
script.awk的内容

FNR==1 {
    FILENAME++
    c=0
}

{
    for (i=1;i<=NF;i++) {
        c++
        a[c] = (a[c] ? a[c] : FILENAME FS NR FS i) FS $i
    }
}

END {
    for (j=1;j<=c;j++) {
        print a[j] > sprintf("%04d.dat", FILENAME)
    }
}

撇开性能不谈,您的Bash脚本并不能满足您的需要。首先--
$j
不是Bash变量,因此
“FNR==i{print$j}”
扩展为
“FNR==i{print}”
,它将打印整个
i
-th行。其次,您选择了令人困惑的变量名(
x
表示时间步而不是x轴,
y
z
表示
i
j
),而不是y轴和z轴),这本身并不是一个错误,但我认为它会导致您意外地转置矩阵。或者您的矩阵实际上是按列主顺序存储的?(我知道您希望完全抛弃Bash脚本,但我提到这些问题,因为在不清楚它应该做什么的情况下,很难编写性能更好的替换。一个清晰、无bug的Bash脚本将非常有用。)现在我看到了你的输出,我仍然不明白为什么你有一个填充零的数组?另外,您使用的是示例调用中指定的值,
-vt=1
。我在您的bash代码中没有看到显式的
${t}
。这是一个非常有趣的问题,但很抱歉,我暂时不能看这个问题。祝你好运。@Sheller:填充零的数组将生成文件名:该数组将(例如)
7
映射到
0006
,因为timestep#7位于
0006.v{x,y,z}.dat
。我假设
-vt=1
表示“timestep#1”,由
stackoverflow.awk
用于生成其输出的第一列。
print j
也不是您想要的:它将打印
j
的值,但您希望打印
j
位置的值。(例如,如果
j
3
,您想打印第三个字段,但是
print j
只会打印数字
3
)您使用
$
是正确的,但是您需要将AWK脚本用单引号括起来,以便在AWK有机会看到它之前Bash不会展开
$j
。谢谢,史提夫!这正好解决了问题。但是,由于某种原因,它保存到的文件名没有进行迭代,所以我只是将mawk的输出通过管道传输到bash中该迭代的文件名中。这是一个真正的救命恩人。我要比以往更加认真地学习awk。像这样的应用在计算科学中是非常令人印象深刻和有用的。我的目标是建立一个文件类型转换库。有一天…最后一个问题,是否要传递一个变量作为第一个条目?也就是说,下一个文件将有:211019等等。我知道我可以向awk命令添加一个-vt=$变量,但我很好奇如何在awk脚本中访问该变量t。我自己解决了:
a[c]=(a[c]?a[c]:FILENAME FS NR FS I)FS$I
变成
a[c]=(a[c]:t FS NR FS I)FS$I
。再次感谢你,史蒂夫@托马斯詹姆斯:很高兴你把它整理好了。干杯
1 1 1 1 10 19
1 1 2 2 11 20
1 1 3 3 12 21
1 2 1 4 13 22
1 2 2 5 14 23
1 2 3 6 15 24
1 3 1 7 16 25
1 3 2 8 17 26
1 3 3 9 18 27