이는 이전 질문에 대한 보다 구체적인 후속 조치입니다(두 파일 간의 산술 연산으로 일련의 새 파일이 생성됩니다.).
다음과 유사한 통합 분석 형식으로 변경하려는 탭으로 구분된 모델 입력 파일이 있습니다.
cat input.txt
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.5 1
abies_grandis 2.5 0.4 1
larix_occidentalis 1.5 0.3 1
아래와 같이 배포판에서 무작위로 선택된 승수 파일이 한 줄에 하나씩 있습니다.
cat multipliers.txt
0.1
0.5
0.25
한 필드(wsg)에 두 번째 파일의 단일 승수를 곱하는 일련의 새 입력 파일을 생성하고 싶습니다. 이 예에서는 3개의 승수에 대한 3개의 새 파일이 있습니다(실제 분석에는 1000개의 승수가 포함됩니다). 출력 파일은 다음과 같습니다.
(wsg * 0.1)cat file1.txt
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.05 1
abies_grandis 2.5 0.04 1
larix_occidentalis 1.5 0.03 1
(wsg * 0.5)cat file2.txt
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.25 1
abies_grandis 2.5 0.2 1
larix_occidentalis 1.5 0.15 1
(wsg*0.25)cat file3.txt
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.125 1
abies_grandis 2.5 0.1 1
larix_occidentalis 1.5 0.075 1
이전 질문을 바탕으로 @EdMorton은 다음을 제안했습니다.
$ 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
이것은 이전 문제에 대한 훌륭한 솔루션이지만 산술은 입력의 각 줄의 마지막 필드에서 수행됩니다. 각 행의 n번째 필드(이 경우 세 번째(wsg))를 처리하도록 수정하고 싶습니다.
답변1
질문을 다시 읽은 후 실제로 다음을 수행할 것을 제안합니다. 이는 어떤 필드가 해당 필드인지 알려주는 것이 아니라 wsg
입력 파일에서 다음으로 시작하는 줄에서 해당 정보를 읽는 것입니다.***
$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR {
if ( tgtFldNr ) {
lines[++numLines] = $0
}
else {
hdr = hdr $0 ORS
if ( /^\*\*\*/ ) { # in case this line is not tab-separated
split($0,f," ")
for (i in f) {
if ( f[i] == "wsg" ) {
tgtFldNr = i-1
break
}
}
}
}
next
}
{
mult = $1
out = "file" FNR ".txt"
printf "%s", hdr > out
for (lineNr=1; lineNr<=numLines; lineNr++) {
$0 = lines[lineNr]
$tgtFldNr *= mult
print > out
}
close(out)
}
$ awk -f tst.awk input.txt multipliers.txt
$ head file*
==> file1.txt <==
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.05 1
abies_grandis 2.5 0.04 1
larix_occidentalis 1.5 0.03 1
==> file2.txt <==
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.25 1
abies_grandis 2.5 0.2 1
larix_occidentalis 1.5 0.15 1
==> file3.txt <==
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.125 1
abies_grandis 2.5 0.1 1
larix_occidentalis 1.5 0.075 1
후손을 위한 원래 답변:
$ cat tst.awk
NR==FNR {
if ( pastHdr ) {
lines[++numLines] = $0
}
else {
hdr = hdr $0 ORS
if ( $1 == "***" ) {
pastHdr = 1
}
}
next
}
{
tgtFldNr = (n ? n : NF)
mult = $1
out = "file" FNR ".txt"
printf "%s", hdr > out
for (lineNr=1; lineNr<=numLines; lineNr++) {
$0 = lines[lineNr]
$tgtFldNr *= mult
print > out
}
close(out)
}
$ awk -v n=3 -f tst.awk input.txt multipliers.txt
$ head file*
==> file1.txt <==
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.05 1
abies_grandis 2.5 0.04 1
larix_occidentalis 1.5 0.03 1
==> file2.txt <==
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.25 1
abies_grandis 2.5 0.2 1
larix_occidentalis 1.5 0.15 1
==> file3.txt <==
/* Preciptation in mm */
10 30 40 50 23
### Species description
*** sp_name LMA wsg a_h
abies_lasiocarpa 2 0.125 1
abies_grandis 2.5 0.1 1
larix_occidentalis 1.5 0.075 1
-v n=<number>
곱할 필드 수를 설정하지 않으면 이전 질문에서 원했던 것처럼 기본적으로 각 행의 마지막 필드를 곱하게 됩니다.
귀하의 질문 텍스트에서 귀하의 입력이 탭으로 구분되어 있다고 말했지만 귀하가 제공한 예에서는 그렇게 보이지 않습니다. 실제로 탭으로 구분된 경우 BEGIN { FS=OFS="\t" }
스크립트 상단, 해당 NR==FNR {
줄 바로 앞에 추가하면 됩니다.