I have an input file input.txt
that contains the following values:
# 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)
where Ti
, Pi
, ui
, vi
, and wi
for i = 0
to N
are floating-point numbers.
I have on the other hand, some directories that correspond to the times:
0 # this is a directory
0.0015 # this is a directory also
0.0021 # ...etc.
0.0028
0.0031
...
...
I have a template myTemplate.txt
file that looks like the following:
# 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%})
My goal is to create a file output.txt
under each time directory using the template file myTemplate.txt
and populate the values from the input file input.txt
.
I have tried the following:
# 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
I am stuck in the step where I need to populate the values in the template file and generate a file output.txt
under each directory.
Any help on how to achieve that or may by suggesting an efficient way to accomplish this task using linux standard utilities such as sed
, awk
is very much appreciated.
CodePudding user response:
I have adapted your bash script which contains multiple typos/errors. This is not the most efficient way to accomplish this but I have tested it on your data and it works:
Create a script file 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
Time=$(echo "$line" | tr -s '[:blank:]' ' ' | cut -d' ' -f1 )
Temperature=$(echo "$line" | tr -s '[:blank:]' ' ' | cut -d' ' -f2 )
Pressure=$(echo "$line" | tr -s '[:blank:]' ' ' | cut -d' ' -f3 )
U=$(echo "$line" | tr -s '[:blank:]' ' ' | tr -d '()' | cut -d' ' -f4 )
V=$(echo "$line" | tr -s '[:blank:]' ' ' | tr -d '()' | cut -d' ' -f5 )
W=$(echo "$line" | tr -s '[:blank:]' ' ' | 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!"
Run the script:
chmod x generate.sh
./generate.sh
I have checked that a file output.txt
is created under each time directory and contains the correct values from input.txt
. The script should also raise an error if a time is not found.
CodePudding user response:
this is a working prototype, note that there is no error handling for missing directories or wrong input formatting etc.
$ awk 'NR==FNR {temp=temp sep $0; 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 > ($1 "/output.txt")}' template.txt input.txt
this only replaces the time but you can repeat the same pattern for the other variables.
Reads the template file and saves in variable temp. Reads the input file and captures the header names for easy reference to array h
. For each data line, do the replacements and save to the corresponding directory (assumes it exists).
This should be trivial to read:
sub("{%TIME%}", $h["t"], text)
substitute {%TIME%}
with the value of $h["t"]
in variable text
.
$h["t"]
means the value at index h["t"]
, which we put the index of t
in the header line, which is 1. So instead of writing $1
we can write $h["t"]
so the variable we're referring to is documented in place.
The other variable you'll refer to again with the names "T", "P", etc.