HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Parsing Gaussian09 frequency calculations, reformatting depending on desired output

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gaussian09frequencyoutputdesiredreformattingcalculationsparsingdepending

Problem

Quite similar to my earlier review this script parses a frequency calculation and reformats the found values to either fit into one row for easier importing into a spreadsheet software or a formatted table.

The whole project including sample calculation files for testing can be found on github. I checked the script with http://www.shellcheck.net/# and there were no warnings left. I am looking for some input, whether I could simplify some of the code or make it more efficient.

```
#!/bin/bash
# Script can be used to parse one (or more) frequency calculation(s)
# of the quantum chemical software suite Gaussian09

# Intitialise scriptoptions
errCount=0
printlevel=0
isOptimisation=0
isFreqCalc=0
ignorePrintlevelSwitch=0

# Initialise all variables that are of interest
declare filename functional temperature pressure
declare electronicEnergy zeroPointEnergy thermalCorrEnergy thermalCorrEnthalpy thermalCorrGibbs
declare -a contributionNames thermalE heatCapacity entropy
declare routeSection

# Errors, Info and Warnings
fatal ()
{
echo "ERROR : " "$@"
exit 1
}

message ()
{
echo "INFO : " "$@"
}

warn ()
{
echo "WARNING: " "$@"
}

# Parse the commands that have been passed to Gaussian09
getRouteSec ()
{
# The route section is echoed in the log file, but it might spread over various lines
# options might be cut off in the middle. It always starts with # folowed by a space
# or the various verbosity levels NPT (case insensitive). The route section is
# terminated by a line of dahes. The script will stop reading the file if encountered.
local line appendline
local addline=0
while read -r line; do
if [[ $line =~ ^[[:space:]]*#[nNpPtT]?[[:space:]] || "$addline" == "1" ]]; then
[[ $line =~ ^[[:space:]][-]+[[:space:]]$ ]] && break
appendline="$appendline$line"
addline=1
fi
done < "$filename"

routeSection="$appendline"
}

# Test the route section if it is an optimis

Solution

Use a for-each loop when the index is not needed

In this loop you don't really need the loop index:

for (( index=0; index < ${#contributionNames[@]}; index++ )); do
     printf "%-10s " "${contributionNames[$index]}"
 done


Since you need just the elements, a for-each loop is more natural:

for name in "${contributionNames[@]}"; do
     printf "%-10s " "$name"
 done


Do the same for the other counting loops too where possible.

Use here-string instead of redirecting echo

Instead of this:

fold -w80 -c -s < <(echo "$routeSection")


Better to use a here-string to avoid an additional process creation:

fold -w80 -c -s <<< "$routeSection"


Use modern (( ... )) consistently

Since you used (( ... )) a lot, I don't understand why you didn't use it here:

if [ ${#values[$index]} -lt ${#header[$index]} ]; then


-lt is old-fashioned, you could use naturally < in a (( ... )).

A consistent writing style improves readability.

Simple scripts evolving into complex programs

This script is getting really complex. Bash is great for simple things, but when things start to get complex, it often becomes a wrestle. I would recommend Python as a scripting language for complex tasks. It has great unit testing facilities too.

Code Snippets

for (( index=0; index < ${#contributionNames[@]}; index++ )); do
     printf "%-10s " "${contributionNames[$index]}"
 done
for name in "${contributionNames[@]}"; do
     printf "%-10s " "$name"
 done
fold -w80 -c -s < <(echo "$routeSection")
fold -w80 -c -s <<< "$routeSection"
if [ ${#values[$index]} -lt ${#header[$index]} ]; then

Context

StackExchange Code Review Q#131666, answer score: 3

Revisions (0)

No revisions yet.