如何通过行号替换文本文件中的整行
上面链接中的问题询问如何替换文本文件中的行。nakeer(从底部开始的第二个答案)提供了一个适合我作为Mac用户的答案:
sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name
然而,我不知道如何根据我的特殊情况修改它。如果有人能给我指出正确的方向,我将不胜感激。
>
我有很多文件。每个文件都包含这个矩阵,如下所示:
12.345678 0.000000 0.000000
0.000000 12.345678 0.000000
0.000000 0.000000 12.345678
我有一个包含一列数字的附加文件,例如:
87.654321
18.765432
21.876543
...
我想从(2)中列的每一行中取一个数字。我想用它来替换(1)中一个矩阵的非零值(保留零值)。所以第一个文件中的第一个矩阵应该如下所示:
87.654321 0.000000 0.000000
0.000000 87.654321 0.000000
0.000000 0.000000 87.654321
第二个文件中的第二个矩阵应使用“18.765432”作为其非零值。
我在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.
更新:
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
有任何想法,我将不胜感激!
$ 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
进行“inplace”编辑,而不是创建新的输出文件,如果这对您有用的话。
按照@Zelnes的想法,这里有一个版本,它只是根据您的file2数据生成一个新文件:
#!/bin/bash
while read value ; do
((fileNum++))
awk -v input="$value" '
END{
for (i=1;i<4;i++) {
for (j=1;j<4;j++) {
#dbg print "#dbg: i=" i "\tj=" j;
if (j==i) {
#dbg print "#dbg: matched"
arr[i]=input
} else {
#dbg print "#dbg: setting arr["j"]="arr[j]
arr[j]=0.0
}
}
printf("%0.6f\t%0.6f\t%0.6f\n",arr[1],arr[2],arr[3])}} ' /dev/null \
> file"$fileNum".txt
done < newValues.txt
可以更改printf
以获得格式问题所需的确切行间距。将末尾的newValue. txt
更改为实际输入文件的名称。您甚至可以将其设为/path/to/一些地方/else/newValue.txt
。
你会需要的
chmod +x myDataGenerator
在运行它之前。
cd
到您要在其中创建文件的目录,然后使用其完整路径调用脚本,即
/full/path/to/myDataGenerator
如果您想要尽可能小的程序,请删除#dbg
行。
如果您想了解脚本的工作原理,请一次取消注释一行#dbg
,了解正在做什么,然后取消注释下一个#dbg
。
IHTH