2 个文件之间的算术生成一系列新文件

2 个文件之间的算术生成一系列新文件

我有一个制表符分隔的模型输入文件,我想针对类似于此的集成分析格式进行更改

输入.txt

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.5
abies_grandis 2.5 0.4
larix_occidentalis 1.5 0.3

我有另一个乘法器文件,每行一个,如下所示

乘数.txt

0.5
0.6
0.7

我想生成一系列新的输入文件,其中一个字段(wsg)乘以第二个文件中的单个乘数。在此示例中,将有 3 个新文件对应于 3 个乘数。输出文件如下所示:

文件1.txt(wsg * 0.5)

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.25
abies_grandis 2.5 0.2
larix_occidentalis 1.5 0.15

文件2.txt(wsg * 0.6)

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.3
abies_grandis 2.5 0.24
larix_occidentalis 1.5 0.18

文件3.txt(wsg * 0.7)

/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.35
abies_grandis 2.5 0.28
larix_occidentalis 1.5 0.21

这似乎可以使用 awk 和 for 循环来完成,但我对 awk 的了解还达不到执行此任务所需的水平。我应该如何处理这个问题?

答案1

在每个 Unix 机器上的任何 shell 中使用任何 awk,无论你现在有多少乘数:

$ ls *.txt
input.txt  multipliers.txt

$ cat tst.awk
NR==FNR {
    if ( pastHdr ) {
        ++numLines
        wsg[numLines] = $NF
        sub(/[[:space:]][^[:space:]]+$/,"")
        rest[numLines] = $0
    }
    else {
        hdr = hdr $0 ORS
        if ( $1 == "***" ) {
            pastHdr = 1
        }
    }
    next
}
{
    out = "file" FNR ".txt"
    printf "%s", hdr > out
    for (lineNr=1; lineNr<=numLines; lineNr++) {
        print rest[lineNr], wsg[lineNr] * $0 > out
    }
    close(out)
}

$ awk -f tst.awk input.txt multipliers.txt

$ ls *.txt
file1.txt  file2.txt  file3.txt  input.txt  multipliers.txt

$ head file*.txt
==> file1.txt <==
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.25
abies_grandis 2.5 0.2
larix_occidentalis 1.5 0.15

==> file2.txt <==
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.3
abies_grandis 2.5 0.24
larix_occidentalis 1.5 0.18

==> file3.txt <==
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.35
abies_grandis 2.5 0.28
larix_occidentalis 1.5 0.21

上面的内容非常相似@guest_7 发布的解决方案,我发布它是因为他们的:

  1. 使用许多单字符变量名称,恕我直言,这样的大小的脚本对于新手来说更难理解,
  2. 用于NF--删除 wsg 值,但递减 NF 是未定义的行为,因此不可移植,并且
  3. 硬编码标题有多少行(这可能没有错,这只是我的偏好通过分析文本来确定 - 但这也可能是错误的,具体取决于真实的输入是否总是看起来像发布的示例,并且,如果不是,有什么不同)。

答案2

假设乘法需要恰好发生在 中第 6 行往后的最后一个空白分隔字段上input.txt。使用简单的 shell 循环:

count=0
while IFS= read -r mult; do
    count=$(( count + 1 ))
    awk -v mult="$mult" 'NR >= 6 { $NF *= mult }; 1' <input.txt >"file$count.txt"
done <multipliers.txt

这会从循环的每次迭代中读取一个乘数,然后将其应用于第6 行( )之后的multipliers.txt最后一个字段( )的值。然后打印每一行,无论是否修改过(这就是尾随的作用)。$NFNR >= 61

输出文件名是通过静态前缀file、计数器count和静态后缀创建的.txt

如果您愿意,您可以删除该multipliers.txt文件(如果您始终有少量不变的乘数):

count=0
for mult in 0.5 0.6 0.7; do
    count=$(( count + 1 ))
    awk -v mult="$mult" 'NR >= 6 { $NF *= mult }; 1' <input.txt >"file$count.txt"
done

答案3

我们将 input.txt 文件读入 awk 数组,因为它们只有 6 行。

awk '
  NR==FNR {
    if (NR<6) {h=h sep $0}
    else {
      n++;    b[n]=$NF
      $NF=""; a[n]=$0
    }
    sep = ORS
    next
  }
  {
    close(f); f = fp($1)
    print h > f
    for (i=1; i<=n; i++) {
      print a[i] b[i]*$1 > f
    }
  }
  function fp(m) {
    sub(/[.]/, "p", m)
    return "file@mult=" m ".txt"
  }
' input.txt multipliers.txt

结果:

.
├── file@mult=0p5.txt
├── file@mult=0p6.txt
├── file@mult=0p7.txt
├── input.txt
└── multipliers.txt

::::::::::::::
file@mult=0p5.txt
::::::::::::::
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.25
abies_grandis 2.5 0.2
larix_occidentalis 1.5 0.15

::::::::::::::
file@mult=0p6.txt
::::::::::::::
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.3
abies_grandis 2.5 0.24
larix_occidentalis 1.5 0.18

::::::::::::::
file@mult=0p7.txt
::::::::::::::
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.35
abies_grandis 2.5 0.28
larix_occidentalis 1.5 0.21

答案4

j=1; while read i; do awk -v i="$i" 'NR>5{$NF=$NF*i}1' input.txt >file$j.txt\(wsg*"$i"\);j=$(($j+1)); done < multipliers.txt

输出

@praveen:~$ cat file1.txt\(wsg\*0.5\) 
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.25
abies_grandis 2.5 0.2
larix_occidentalis 1.5 0.15

===========
praveen@praveen:~$ cat file2.txt\(wsg\*0.6\) 
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.3
abies_grandis 2.5 0.24
larix_occidentalis 1.5 0.18

========

praveen@praveen:~$ cat file3.txt\(wsg\*0.7\) 
/* Preciptation in mm */
10 30 40 50 23

### Species description
*** sp_name LMA wsg
abies_lasiocarpa 2 0.35
abies_grandis 2.5 0.28
larix_occidentalis 1.5 0.21

Python

#!/usr/bin/python
mu=open('Multipliers.txt','r')
ik=open('input.txt','r')
t=ik.readlines()
d=1
for g in mu:
    er=open("file{0}.txt(wsg*{1})".format(d,g.strip()),'w')
    for h in range(0,len(t),1):
        if (int(h) < 5):
            print t[h].strip()
            er.write(t[h].strip())
            er.write('\n')
        else:
            k=t[h].split(' ')
            co=float(k[-1].strip())*float(g)
            print " ".join(k[0:-1])+" "+str(co)
            er.write(" ".join(k[0:-1])+" "+str(co))
            er.write('\n')
    d=d+1        

相关内容