我有一个制表符分隔的模型输入文件,我想针对类似于此的集成分析格式进行更改
输入.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 发布的解决方案,我发布它是因为他们的:
- 使用许多单字符变量名称,恕我直言,这样的大小的脚本对于新手来说更难理解,
- 用于
NF--
删除 wsg 值,但递减 NF 是未定义的行为,因此不可移植,并且 - 硬编码标题有多少行(这可能没有错,这只是我的偏好通过分析文本来确定 - 但这也可能是错误的,具体取决于真实的输入是否总是看起来像发布的示例,并且,如果不是,有什么不同)。
答案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
最后一个字段( )的值。然后打印每一行,无论是否修改过(这就是尾随的作用)。$NF
NR >= 6
1
输出文件名是通过静态前缀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