Home > OS >  How to find content in a file and replace the adjecent value
How to find content in a file and replace the adjecent value

Time:10-24

Using bash how do I find a string and update the string next to it for example pass value

my.site.com|test2.spin:80

proxy_pass.map

my.site2.com           test2.spin:80
my.site.com            test.spin:8080;

Expected output is to update proxy_pass.map with

my.site2.com           test2.spin:80
my.site.com            test2.spin:80;

I tried using awk

awk '{gsub(/^my\.site\.com\s [A-Za-z0-9] \.spin:8080;$/,"my.site2.comtest2.spin:80"); print}' proxy_pass.map

but does not seem to work. Is there a better way to approch the problem. ?

CodePudding user response:

With your shown samples and attempts please try following awk code. Creating shell variable named var where it stores value my.site.com|test2.spin:80 in it. which further is being passed to awk program. In awk program creating variable named var1 which has shell variable var's value in it.

In BEGIN section of awk using split function to split value of var(shell variable's value container) into array named arr with separator as |. Where num is total number of values delimited by split function. Then using for loop to be running till value of num where it creates array named arr2 with index of current i value and making i 1 as its value(basically 1 is for key of array and next item is value of array).

In main block of awk program checking condition if $1 is in arr2 then print arr2's value else print $2 value as per requirement.

##Shell variable named var is being created here...
var="my.site.com|test2.spin:80"

awk -v var1="$var" '
BEGIN{
  num=split(var1,arr,"|")
  for(i=1;i<=num;i =2){
    arr2[arr[i]]=arr[i 1]
  }
}
{
  print $1,(($1 in arr2)?arr2[$1]:$2)
}
' Input_file


OR in case you want to maintain spaces between 1st and 2nd field(s) then try following code little tweak of Above code. Written and tested with your shown samples Only.

awk -v var1="$var" '
BEGIN{
  num=split(var1,arr,"|")
  for(i=1;i<=num;i =2){
    arr2[arr[i]]=arr[i 1]
  }
}
{
  match($0,/[[:space:]] /)
  print $1 substr($0,RSTART,RLENGTH) (($1 in arr2)?arr2[$1]:$2)
}
'   Input_file

NOTE: This program can take multiple values separated by | in shell variable to be passed and checked on in awk program. But it considers that it will be in format of key|value|key|value... only.

CodePudding user response:

If the number of spaces between the columns is not significant, a simple

proxyf=proxy_pass.map
tmpf=$$.txt
awk '$1 == "my.site.com" { $2 = "test2.spin:80;" } {print}' <$proxyf >$tmpf && mv $tmpf $proxyf

should do. If you need the columns to be lined up nicely, you can replace the print by a suitable printf .... statement.

CodePudding user response:

One awk idea, assuming spacing needs to be maintained:

awk -v rep='my.site.com|test2.spin:80' '

BEGIN      { split(rep,a,"|")                                   # split "rep" variable and store in 
             site[a[1]]=a[2]                                    # associative array
           }

$1 in site { line=$0                                            # if 1st field is in site[] array then make copy of current line

             match(line,$1)                                     # find where 1st field starts (in case 1st field does not start in column #1)
             newline=substr(line,1,RSTART RLENGTH-1)            # save current line up through matching 1st field
             line=substr(line,RSTART RLENGTH)                   # strip off 1st field

             match(line,/[^[:space:];] /)                       # look for string that does not contain spaces or ";" and perform replacement, making sure to save everything after the match (";" in this case)
             newline=newline substr(line,1,RSTART-1) site[$1] substr(line,RSTART RLENGTH)

             $0=newline                                         # replace current line with newline
           }
1                                                               # print current line
' proxy_pass.map

This generates:

my.site2.com           test2.spin:80
my.site.com            test2.spin:80;

If the input looks like:

$ cat proxy_pass.map
my.site2.com           test2.spin:80
  my.site.com          test.spin:8080;

This awk script generates:

my.site2.com           test2.spin:80
  my.site.com          test2.spin:80;

NOTES:

  • if multiple replacements need to be performed I'd suggest placing them in a file and having awk process said file first
  • the 2nd match() is hardcoded based on OP's example; depending on actual file contents it may be necessary to expand on the regex used in the 2nd match()

CodePudding user response:

#!/bin/sh -x

f1=$(echo "my.site.com|test2.spin:80" | cut -d'|' -f1)
f2=$(echo "my.site.com|test2.spin:80" | cut -d'|' -f2)

echo "${f1}%${f2};" >> proxy_pass.map
tr '%' '\t' < proxy_pass.map >> p1
cat > ed1 <<EOF
$
-1
d
wq
EOF
ed -s p1 < ed1
mv -v p1 proxy_pass.map
rm -v ed1
  • Related