Home > Software design >  awk with bash variable along with condition to be checked
awk with bash variable along with condition to be checked

Time:08-11

I need to search and replace a pattern from file

[ec2_server]
server_host=something

[list_server]
server_host=old_name 

to

[ec2_server]
server_host=something

[list_server]
server_host=new_name

I'm able to get it working with awk '/\[list_server]/ { print; getline; $0 = "server_host=new_name" } 1'

But I'm trying to parameterize the search pattern, the parameter name to change and the parameter value to change.

PATTERN_TO_SEARCH=[list_server]

PARAM_NAME=server_host

PARAM_NEW_VALUE=new_name

But it is not working when I parameterize and pass the variables to awk

awk -v patt=$PATTERN_TO_SEARCH -v parm=$PARAM_NAME -v parmval=$PARAM_NEW_VALUE '/\patt/ { print; getline; $0 = "parm=parmval" } 1' file.txt

CodePudding user response:

You have two instances of the same problem: you're trying to use a variable name inside a string value. Awk can't read your mind: it can't intuit that sometimes when your write "HOME" you mean "print the value of the variable HOME" and other times you mean "print the word HOME".

We need to make two separate changes:

First, to use a variable in your search pattern, you can use syntax like this:

awk -v patt='some text' '$0 == patt {print}'

(Note that here we're using an equality match, ==; you can also use a regular expression match, ~, but in this particular case that would only complicate things).

With your example file content, running:

awk -v patt='[list_server]' '$0 == patt {print}' file.txt

Produces:

[list_server]

Next, when you write $0 = "parm=parmval", you're setting $0 to the literal string parm=parmval. If you want to perform variable substitution, consider using sprintf():

awk \
  -v patt=$PATTERN_TO_SEARCH \
  -v parm=$PARAM_NAME \
  -v parmval=$PARAM_NEW_VALUE \
  '
    $0 == patt { print; getline; $0 = sprintf("%s=%s\n", parm, parmval) } 1
  ' file.txt

Which gives us:

[ec2_server]
server_host=something

[list_server]
server_host=new_server

CodePudding user response:

Have your awk code in following way, as experts recommend not to use getline(since it has edge cases in its use). So I am going with find the string and then set flag(custom variable made by me in program) and then print the line accordingly with using regex along with passed value from shell variable.

Along with matching and printing the new value we need to set field separator also to fetch correct value and replace/print it with new value. So I made field separator as = here for whole Input_file. By doing this approach you need not to pass any variable which has server_host value in it, since its already present in Input_file so we can take it from there.

awk solution with mentioning value within awk variable itself and then check regex in main program of awk for comparison.

awk -v var="list_server" -v newVal="NEW_VALUE" '
BEGIN{ FS=OFS="=" }
$0 ~ "^\\[" var "\\]$"{
  found=1
  print
  next
}
found{
  print $1 OFS newVal
  found=""
  next
}
1
' Input_file


OR awk solution to get value from shell variable and then use regex inside awk to match condition:

varS="list_server"   ##Shell variable
newvalue="NEW_VALUE" ##Shell variable

awk -v var="$varS" -v newVal="$newvalue" '
BEGIN{ FS=OFS="=" }
$0 ~ "^\\[" var "\\]$"{
  found=1
  print
  next
}
found{
  print $1 OFS newVal
  found=""
  next
}
1
' Input_file

CodePudding user response:

This makes the assumption "${PARAM_NAME}" immediately follows the search pattern row :

      _P2S_='[list_server]'
      _PNM_='server_host'
      _PNV_='new_name'

echo "${...input...}" | gtee >( gpaste - | gcat -b >&2; echo ) | gcat - | 

{m,n,g}awk -v __="${_P2S_}=${_PNM_}=${_PNV_}" -F= 'BEGIN {

     $(_-=_)=__;___= $(_ = NF);   FS ="^"(OFS = $--_ FS)
 __= $-(_ =-_--) } (NR-_)< NF ? ($NF =___)^(_-=_) :_=NR*(-!!_)^(__!=$!_)' |  

gcat -b | gcat -n | ecp 
 1  [ec2_server]
 2  server_host=something

 3  [list_server]
 4  server_host=old_name 


 1       1  [ec2_server]
 2       2  server_host=something
 3  
 4       3  [list_server]
 5       4  server_host=new_name
  • Related