使用模板文件和输入文件在子目录下生成多个文件

Generate multiple files under subdirectories using a template file and an input file

我有一个包含以下值的输入文件 input.txt

# time(t) Temperature Pressure Velocity(u, v, w)
t  T  P   u v w

0       T0 P0 (u0 v0 w0)
0.0015  T1 P1 (u1 v1 w1)
0.0021  T2 P2 (u2 v2 w2)
0.0028  T3 P3 (u3 v3 w3)
0.0031  T4 P4 (u4 v4 w4)
0.0041  T5 P5 (u5 v5 w5)
...    ...  ... ... ...
...    ...  ... ... ...
1.5001  TN PN (uN vN wN)

其中 TiPiuivii = 0Nwi 是浮动的-点数。

另一方面,我有一些目录与时代相对应:

0      # this is a directory
0.0015 # this is a directory also
0.0021 # ...etc.
0.0028
0.0031
...
...

我有一个模板 myTemplate.txt 文件,如下所示:

# This is my template file

The time of the simulation is: {%TIME%}

The Temperature is {%T%}
The pressure is {%P%}
The velocity vector is: ({%U%} {%V%} {%W%})

我的目标是使用模板文件 myTemplate.txt 在每个时间目录下创建一个文件 output.txt 并填充输入文件 input.txt.

中的值

我试过以下方法:

# assume the name of the directory perfectly matches the time in input file
inputfile="input.txt"
times = $(find . -maxdepth 1 -type d)
for eachTime in $times
do
   line=$(sed -n "/^$eachTime/p" $inputfile)
   T=$(echo "$line" cut -f2 ) # get temperature
   P=$(echo "$line" | cut -f3 ) # get pressure
   U=$(echo "$line" | cut -f4 | tr -d '(') # remove '('
   V=$(echo "$line" | cut -f5 )
   W=$(echo "$line" | cut -f6 | tr -d ')' ) # remove ')'
   
  # I am stuck here, How can I generate a file output.txt from
  # the template and save it under the directory.
done

我卡在了需要在模板文件中填充值并在每个目录下生成一个文件output.txt的步骤。

非常感谢任何关于如何实现该目标的帮助,或者建议使用 linux 标准实用程序(例如 sedawk 来完成此任务的有效方法。

这是一个工作原型,请注意没有针对丢失目录或错误输入格式等的错误处理。

$ awk 'NR==FNR {temp=temp sep [=10=]; sep=ORS;next} 
       FNR==2  {for(i=1;i<=NF;i++) h[$i]=i} 
       FNR>3   {text=temp; 
                sub("{%TIME%}", $h["t"] ,text); 
                # add other sub(..., text) substitutions!
                print text > ( "/output.txt")}' template.txt input.txt

这只会替换时间,但您可以对其他变量重复相同的模式。

读取模板文件并保存在变量 temp 中。读取输入文件并捕获 header 名称以便于引用数组 h。对于每一行数据,做替换并保存到相应的目录(假设它存在)。

这应该是微不足道的阅读:

sub("{%TIME%}", $h["t"], text){%TIME%} 替换为变量 text$h["t"] 的值。

$h["t"] 表示索引 h["t"] 处的值,我们将 t 的索引放在 header 行中,即 1。所以而不是写 </code> 我们可以写成 <code>$h["t"] 这样我们引用的变量就被记录在案了。 您将使用名称“T”、“P”等再次引用的另一个变量

我已经改编了您的 bash 脚本,其中包含多个 typos/errors。 这不是实现此目的的最有效方法,但我已经在您的数据上对其进行了测试并且有效:

创建脚本文件generate.sh:

#!/bin/bash

timedir=$(find * -maxdepth 1 -type d) # use * to get rid of ./ at the beginning
templateFile='./myTemplate.txt' # the path to your template file

for eachTime in $timedir
do

    
    # use bash substitution to replace . with \. in times
    # in order to avoid unexpected matches
    line="$(grep -m 1 -e '^'${eachTime//./\.} input.txt)"

    if [ -z "$line" ]
    then
        echo "***Error***: Data at time: $eachTime were not found!" >&2
        exit 1
    fi
    # the line below is redundant since time is already known
    # replace tabs/and spaces with a single space
    line=$(echo "$line" | tr -s '[:blank:]' ' ' )
    Time=$(echo "$line" | cut -d' ' -f1 )
    Temperature=$(echo "$line" | cut -d' ' -f2 )
    Pressure=$(echo "$line" | cut -d' ' -f3 )
    U=$(echo "$line" | tr -d '()' | cut -d' ' -f4 )
    V=$(echo "$line" | tr -d '()' | cut -d' ' -f5 )
    W=$(echo "$line" | tr -d '()' | cut -d' ' -f6 )

    # Create a temporary file
    buff_file="$(mktemp)"

    # Copy the template to that file
    cp "$templateFile" "$buff_file"

    # Use sed to replace the values
    sed -i "s/{%TIME%\}/$eachTime/g" "$buff_file"
    sed -i "s/{%T%}/$Temperature/g" "$buff_file"
    sed -i "s/{%P%}/$Pressure/g" "$buff_file"
    sed -i "s/{%U%}/$U/g" "$buff_file"
    sed -i "s/{%V%}/$V/g" "$buff_file"
    sed -i "s/{%W%}/$W/g" "$buff_file"

    # Copy that temporary file under the time directory
    cp "$buff_file" "$eachTime"/output.txt
    # delete the temporary file
    rm "$buff_file"

done


echo "Done!"

运行 脚本:

chmod +x generate.sh
./generate.sh

我检查过每个时间目录下都创建了一个文件 output.txt,并且包含来自 input.txt 的正确值。如果找不到时间,脚本也应该引发错误。