首页 > 解决方案 > 如何用另一个文本文件(OSX Sierra,bash)中的数字替换文本文件中的矩阵条目

问题描述

如何用行号替换文本文件中的整行

上面链接中的问题询问如何替换文本文件中的一行。nakeer (从底部开始的第二个答案)提供了一个适合我作为 Mac 用户的答案:

sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name

但是,我无法弄清楚如何针对我的特定情况进行修改。如果有人能指出我正确的方向,我将不胜感激。

  1. 我有很多文件。每个文件都包含这个矩阵,如下所示:

    12.345678    0.000000    0.000000    
     0.000000   12.345678    0.000000    
     0.000000    0.000000   12.345678
    
  2. 我有一个包含一列数字的附加文件,例如:

    87.654321   
    18.765432    
    21.876543
    ...
    
  3. 我想从 (2) 列的每一行中取一个数字。我想用它来替换(1)中一个矩阵的非零值(保留零值)。所以第一个文件中的第一个矩阵应该如下所示:

    87.654321    0.000000    0.000000    
     0.000000   87.654321    0.000000    
     0.000000    0.000000   87.654321
    

第二个文件中的第二个矩阵应使用“18.765432”作为其非零值。

  1. 我没有 bash 脚本方面的经验,但到目前为止我有(其中 ic 是我在 (1) 中的文件,其中包含原始矩阵,我将它复制到一个新目录中,我可以在其中将该矩阵更改为 (3)) :

    #!/bin/bash
    
    let timesteps=20000
    for ((step=0; step <= timesteps ; step++))
    do
      mkdir $step/results
      cp ic $step/ic
    
      cat X >> X # <--Here I'd like to modify nakeer's expression. Any hints would be much appreciated.
    

更新:

  1. 我已经设法让 Ed 非常清晰的解决方案启动并运行。然而,有一个问题。包含矩阵的文件(参见上面的(1))还包含其他数据。例如(在执行 Ed 的代码之前):
    12.345678    0.000000    0.000000    
     0.000000   12.345678    0.000000    
     0.000000    0.000000   12.345678
   0.5   
   abc.xyx 
   90
   900
   0.125
   90
   6

Ed 的代码成功地12.345678将矩阵更改为新值。但是,0.125在下面的数字列表中,矩阵也更改为该新值。我不想0.125被改变。

Ed 下面的代码match似乎使用数字的格式来识别要更改的数字,并且看起来0.125属于应该更改的数字类别。如果有人对如何排除0.125更改有任何想法,我将不胜感激!

  1. 在每个矩阵文件都在自己的目录中的情况下,如何修改 Ed 的代码;例如0/file0, 1/file1, 2/file2,等?

标签: bashtextsedreplaceio

解决方案


$ ls
file1  file2  file3  numbers  tst.awk

.

$ cat tst.awk
NR==FNR { a[NR]=$1; next }

FNR==1 {
    close(out)
    out = FILENAME ".new"
    fileNr++
}

match($0,/[0-9.]+[1-9][0-9.]+/) {
    $0 = substr($0,1,RSTART-1) a[fileNr] substr($0,RSTART+RLENGTH)
}

{ print > out }

.

$ tail -n +1 numbers file*
==> numbers <==
87.654321
18.765432
21.876543

==> file1 <==
12.345678    0.000000    0.000000
 0.000000   12.345678    0.000000
 0.000000    0.000000   12.345678

==> file2 <==
12.345678    0.000000    0.000000
 0.000000   12.345678    0.000000
 0.000000    0.000000   12.345678

==> file3 <==
12.345678    0.000000    0.000000
 0.000000   12.345678    0.000000
 0.000000    0.000000   12.345678

.

$ awk -f tst.awk numbers file1 file2 file3

.

$ ls
file1  file1.new  file2  file2.new  file3  file3.new  numbers  tst.awk

.

$ tail -n +1 file*.new
==> file1.new <==
87.654321    0.000000    0.000000
 0.000000   87.654321    0.000000
 0.000000    0.000000   87.654321

==> file2.new <==
18.765432    0.000000    0.000000
 0.000000   18.765432    0.000000
 0.000000    0.000000   18.765432

==> file3.new <==
21.876543    0.000000    0.000000
 0.000000   21.876543    0.000000
 0.000000    0.000000   21.876543

如果您安装了 GNU awk,那么您可以使用它-i inplace来进行“就地”编辑,而不是创建新的输出文件(如果这对您有用的话)。


推荐阅读