Multline Bash Variable Replacement

I’ve recently needed to append several lines of data to a SAS data step that I collected and built via a shell script. For search-and-replace in bash I typically use sed, but this time I ran into a problem - sed does not like multiline shell variables. Thanks to Stack, I found a way to accomplish this task using awk instead.

Suppose you have a file called data.sas with the following contents:

data person;
   infile datalines delimiter=','; 
   input name :$10. dept :$30.;
   datalines4;                      
John,Sales
Mary,Accounting
Theresa,Management
Stewart,HR
;;;;
run;

Note that I am using a datalines4 statement so that I get an easy to identify target for the substitution. I want to insert a multiline shell variable before the ;;;; to add my data to this data step. Say I have the following variable:

NEWDATA=$(cat <<-END
Will,Compliance
Sidney,Management
END
)

If I try to use sed (sed "s/\;\{4\}/$DATA\n;;;;/" data.sas) I will get an error about an unterminated s command. Instead of sed, I can use awk with a variable to achieve the same goal:

awk -v r="$NEWDATA\n;;;;" '{gsub(/;{4}/, r)}1' data.sas

The one downside is that awk does not have an in-place option like sed, and if I try to redirect to the same file I’m reading from I get an empty file out. So you’ll have to rename the original file in your processing script to achieve a similar effect as with the inplace option in sed.

For additional approaches, see this StackOverflow Question.

D. Michael Senter
D. Michael Senter
Research Statistician Developer

My research interests include data analytics and missing data.

Related