abhinav251288
abhinav251288

Reputation: 35

Not able to pass commandline parameters to awk script embedded in bash script

I am using the below script to try to search and replace multiline pattern using awk . The awk script when used directly works fine but while trying the implement the functionality through a bash script by passing command line arguments , the arguments do not get placed into awk as expected and produce undesirable results . A sample file I used to test the awk script and expected result is as below :

File :

<A>
<B>
Port id=X
<C>
Port id=hey
Port no=hi
</C>
</B>
Port id=Z
</A>

Now if I want to replace the 'Port' by Network' , but only under the scope .. , I would simply run the awk as below and that does the trick :

awk '/<A>/,/<C>/ {gsub(/Port/,"Network"); } {print;}' filename

Output :

<A>
<B>
Network id=X
<C>
Port id=hey
Port no=hi
</C>
</B>
Port id=Z
</A>

I am trying to make the functionality generic by writing a script as below which takes the filename , scope , pattern to be replaced and pattern to be put in place as command line parameters and use them in awk script , however it doesn't work .

Could any one please help with how to pass the command line parameters to awk script to achieve the functionality that I could implement by executing the awk script directly ?

#!/bin/bash

echo "Enter file-name ,scope to be matched separated with space , pattern to be replaced , pattern to be placed"
echo "The file name is :$1 ,the scope to be matched : $2 - $3 , the pattern to be replaced is :$4 , pattern to be placed is: $5"
echo "Scope Start : $2"
echo "Scope End : $3"

awk -v F=$1 -v SS=$2 -v SE=$3 -v RE=$5 -v TRE=$4 '/"$SS"/,/"$SE"/ {gsub(/'"$TRE"'/,RE); } {print;}' "$1"

Upvotes: 1

Views: 351

Answers (1)

Wintermute
Wintermute

Reputation: 44063

Several things:

  1. In awk scripts, $ is not used to expand a variable (unlike shell). Just use the variable name. $ makes it refer to a field -- for example, foo = 1; print $foo will print the first field ($1).
  2. While you cannot use awk variables inside // markers, you can match against regexes contained in variables with ~, as in $0 ~ some_variable. Ranges can be specified as usual with that.
  3. Shell variables should very nearly always be quoted, and passing them to awk's -v option is no exception.

So, putting it all together, you could do it like this:

awk -v SS="$2" -v SE="$3" -v TRE="$4" -v RE="$5" '$0 ~ SS,$0 ~ SE { gsub(TRE, RE) } { print }' "$1"

Where the awk code is

$0 ~ SS, $0 ~ SE {  # between lines that match SS and SE,
  gsub(TRE, RE)     # replace stuff that matches TRE with RE
}
{ print }           # and print everything.

Upvotes: 2

Related Questions