Hello,
I have this awk code in a bash script to perform a find and replace task. This finds one unique line in a file and substitutes the found line with a replacement.
#! /bin/bash
# value determined elsewhere
total_outputs_p1=100
# file being modified
filename='./common_depend/UTILPARAMS.DAT'
# comment lines to ignore
comment_ch="C"
# line being searched for to replace
look_for=" PARAMETER \(SIZEXX = "
# value of replacement line
replace_with=" PARAMETER (SIZEXX = $total_outputs_p1)"
# temporarily add variable values to environment varialbes
export comment_ch look_for replace_with
# process file with awk to find $look_for and replace with $replace_with
# if the first character(s) are are a comment, print the unmodified line
# if the line contains the string we are looking for, print the replacement line
# in all other cases, print the unmodified line
awk ' { if( substr($0,1,1) == ENVIRON["comment_ch"] || if( substr($0,1,2) == ENVIRON["comment_ch"] )
print $0;
else if($0 ~ ENVIRON["look_for"])
print ENVIRON["replace_with"];
else
print $0;
} ' $filename > tmp
# overwrite original file
mv tmp $filename
# clear variables set for this call to awk
unset ENVIRON["comment_ch"]
unset ENVIRON["look_for"]
unset ENVIRON["replace_with"]
This works well. It is rather involved for a simple find and replace but there are other conditions to consider. First, the line with $look_for
is only unique in live code. The string may also exist in lines that have been commented out. Lines with a leading comment character need to be ignored. Also, $look_for
often contains spaces and/or special characters that need to be escaped. I have had allot of trouble defining such values in awk using -v. Exporting the value of the string I am looking for to an environment variable allows me to use test the value in the awk call, including any spaces and necessary escape characters. I unset the environment variables immediately afterwords.
I have a dozen or so of these tasks to perform, so the logical structure is to have this code in a function to which the values for $filename
, comment_ch
, $look_for
, and $replace_with
are passed in the call. I have set it up in a function and printed the values from inside the function.
the code looks like,
#! /bin/bash
# function to call awk and implement find and replace
function find_and_replace () {
# leading comment character (ignore line and print)
local f_comment_ch=$1
# line in file to find and replace
local f_look_for=$2
# replacement line
local f_replace_with=$3
# original filename
local f_filename=$4
echo " in function"
echo " f_comment_ch: " $f_comment_ch
echo " f_look_for: " $f_look_for
echo "f_replace_with: " $f_replace_with
echo " f_filename: " $f_filename
echo ""
# add variables to ENVIRON
export f_comment_ch f_look_for f_replace_with
# process file with awk to find $look_for and replace with $replace_with
awk ' { if( substr($0,1,1) == ENVIRON["comment_ch"] || if( substr($0,1,2) == ENVIRON["comment_ch"] )
print $0;
else if($0 ~ ENVIRON["f_look_for"])
print ENVIRON["f_replace_with"];
else
print $0;
} ' $f_filename > tmp
# overwrite original file
mv tmp $f_filename
# clear variables set for this call to awk
unset ENVIRON["f_comment_ch"]
unset ENVIRON["f_look_for"]
unset ENVIRON["f_replace_with"]
}
# value determined elsewhere
total_outputs_p1=100
# file being modified
filename='./common_depend/UTILPARAMS.DAT'
# comment lines to ignore
comment_ch="C"
# line being searched for to replace
look_for=" PARAMETER \(SIZEXX = "
# value of replacement line
replace_with=" PARAMETER (SIZEXX = $total_outputs_p1)"
# call find and replace
find_and_replace "$comment_ch" "$look_for" "$replace_with" "$filename"
This correctly prints the argument values from inside the function but the output I get is just a few lines with a single space. This doesn't make any sense. I am guessing that there may be some issue with the local environment inside the subshell for the function or the call to awk, but if ENVIRON["f_look_for"]
evaluates to uninitialized, based on the logic in the awk code I would expect the entire unmodified file to be printed since neither the $comment_ch
or $look_for
would ever be found.
I'm not sure what to try next so I thought I would post.
Thanks,
LMHmedchem