1

I'm trying to write a shell script that reads over a hundred files containing multiple sections of parameters in each file, just to modify one line. If a section in one file does not contain ELLIPSOID_CODE = 123, add in line ELLIPSOID_CODE = DEFAULT before OUTPUT_PARAMETER. If a section in one file does contain ELLIPSOID CODE = 123, don't do anything. I am having trouble parsing in shell script to get this to work. I have an example of a file and my attempted code below.

-----------------------------------------------------------------------   ------
NUM_RUNS = 2 

INPUT_FILE = /home/autotest
OUTPUT_PROJECTION_TYPE = BLAH
ELLIPSOID_CODE = 123
OUTPUT_PARAMETER = BLAH
OUT_FILE = /home/autotest

INPUT_FILE = /home/autotest
OUTPUT_PROJECTION_TYPE = BLAH
OUTPUT_PARAMETER = BLAH
OUT_FILE = /home/autotest

-------------------------------------------------------------------------------

#Adds in the line "ELLIPSOID_CODE = DEFAULT" before OUTPUT_PARAMETER 

dir="/home/autotest/test/"
for i in "$dir"/*;
do
    sed -i 's:OUTPUT_PARAMETER:ELLIPSOID_CODE = DEFAULT\nOUTPUT_PARAMETER:' "$i";
done

My code adds in the ELLIPSOID_CODE = DEFAULT in every section no matter, when I just want it to add that line in in the second section of just this one file. Just to clarify I'm trying to get it to look like this:

-----------------------------------------------------------------------------
NUM_RUNS = 2 

INPUT_FILE = /home/autotest
OUTPUT_PROJECTION_TYPE = BLAH
ELLIPSOID_CODE = 123
OUTPUT_PARAMETER = BLAH
OUT_FILE = /home/autotest

INPUT_FILE = /home/autotest
OUTPUT_PROJECTION_TYPE = BLAH
ELLIPSOID_CODE = DEFAULT
OUTPUT_PARAMETER = BLAH
OUT_FILE = /home/autotest

-------------------------------------------------------------------------------
3
  • Is the order of parameters in each section guaranteed to be always the same (as in your example above) ? Jan 11, 2018 at 21:45
  • Yes, it is. "ELLIPSOID_CODE = 123" would always be after "OUTPUT_PROJECTION_TYPE" if it appeared. And you would always insert "ELLIPSOID_CODE = DEFAULT" before OUTPUT_PARAMETER if "ELLIPSOID_CODE = 123" did not appear in that section.
    – dhboots
    Jan 11, 2018 at 22:22
  • In that case you've already got a working answer (though using s to insert lines is really ugly..) Jan 11, 2018 at 22:23

2 Answers 2

3

sed solution:

sed -i '/^OUTPUT_PROJECTION_TYPE = .*/{ 
           N; s/OUTPUT_PARAMETER = .*/ELLIPSOID_CODE = DEFAULT\n&/; 
       }' /home/autotest/test/*
  • /^OUTPUT_PROJECTION_TYPE = .*/ - for each line started with pattern OUTPUT_PROJECTION_TYPE = .*(where ^ is regex anchor indicating the start of the string/line):
    • N - add a newline to the pattern space, then append the next line of input to the pattern space
    • s/OUTPUT_PARAMETER = .*/ELLIPSOID_CODE = DEFAULT\n&/ - if the next line is OUTPUT_PARAMETER = .* (which means that ELLIPSOID_CODE = ... is missed) - prepend it with default line ELLIPSOID_CODE = DEFAULT. (& points to the whole matched string)
2
  • Perfect, thank you. Just for clarification if you had time, what is the purpose of the '^', 'N', '&', and the braces{}? Thanks again! @RomanPerekhrest
    – dhboots
    Jan 11, 2018 at 22:35
  • @dhboots,welcome, see my explanation Jan 11, 2018 at 22:47
0

First i found the line numbers for the pattern OUTPUT_PARAMETER. Then assigned the variable j to line number of pattern exists second time and then i replaced on line number as per requirement. Let me know for any doubts

command

j=`sed -n '/OUTPUT_PARAMETER/{;=;p}' filename|sed 'N;s/\n/ /g'| awk 'NR==2{print $1}' | sed -r "s/\s+//g" | sed '/^$/d'`


sed "`echo $j`s/OUTPUT_PARAMETER = BLAH/ELLIPSOID_CODE = DEFAULT\n&/g" filename

output

NUM_RUNS = 2

INPUT_FILE = /home/autotest
OUTPUT_PROJECTION_TYPE = BLAH
ELLIPSOID_CODE = 123
OUTPUT_PARAMETER = BLAH
OUT_FILE = /home/autotest

INPUT_FILE = /home/autotest
OUTPUT_PROJECTION_TYPE = BLAH
ELLIPSOID_CODE = DEFAULT
OUTPUT_PARAMETER = BLAH
OUT_FILE = /home/autotest

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .