使用模板文件和输入文件在子目录下生成多个文件
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)
其中 Ti
、Pi
、ui
、vi
和 i = 0
到 N
的 wi
是浮动的-点数。
另一方面,我有一些目录与时代相对应:
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 标准实用程序(例如 sed
、awk
来完成此任务的有效方法。
这是一个工作原型,请注意没有针对丢失目录或错误输入格式等的错误处理。
$ 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
的正确值。如果找不到时间,脚本也应该引发错误。
我有一个包含以下值的输入文件 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)
其中 Ti
、Pi
、ui
、vi
和 i = 0
到 N
的 wi
是浮动的-点数。
另一方面,我有一些目录与时代相对应:
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 标准实用程序(例如 sed
、awk
来完成此任务的有效方法。
这是一个工作原型,请注意没有针对丢失目录或错误输入格式等的错误处理。
$ 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
的正确值。如果找不到时间,脚本也应该引发错误。