Search a string,get line and replace with second field

Hi,

I need to search for source path in file2 , as per file1 and if found get the next line and take the field value and put it in URL value of file1.
In file1, NF is not same for all the lines.

file1:

<type source="/home/USER/Desktop" Dest="/home/USER/DIR1/Desktop" URL="ssh/path"/>
<type source="/home/USER/OP1" URL="internet/external/path"/>
<type source="/home/USER/Exe" Dest="/home/USER/DIR1/Exe" URL="intranet/path/add"/>

file2:

<path source="/home/USER/Desktop" value="/home/USER/XYZ/Desktop">
    <key value="customer/priority"/>
    <scm tool="toolname/revision"/>
.... some line here
  </path>

<path source="/home/USER/OP1" value="/home/USER/XYZ/ABC/OP1">
    <key value="customer/priority2"/>
    <scm tool="toolname/revision"/>
.... few more lines
  </path>

<path source="/home/USER/Exe" value="/home/USER/XYZ/ABC/Exe">
    <key value="customer/priority4"/>
    <scm tool="toolname/revision"/>
.... few more lines
  </path>

code tried:

awk -F\" '/^<type/ {print $2}' file1 > a.xml
while read line
do
OUTPUT=`awk -F\" -v b="$line" '$0 ~ b {getline; print $2}' file2`
awk -F\" -v proj="$line" -v repl=ref/img/"$OUTPUT" '$0 ~ proj { $6=repl;print $0}' OFS=\" file1
done < a.xml > OUTPUT

Desired output:

<type source="/home/USER/Desktop" Dest="/home/USER/DIR1/Desktop" URL="ref/img/customer/priority"/>
<type source="/home/USER/OP1" URL="ref/img/customer/priority2"/>
<type source="/home/USER/Exe" Dest="/home/USER/DIR1/Exe" URL="ref/img/customer/priority4"/>

I appreciate your help.

---------- Post updated 16th May 2012 at 01:35 AM ---------- Previous update was 15th May 2012 at 07:00 AM ----------

Any other approach than given try?

( Though pumping is not allowed :eek: )

still no idea :frowning:

# awk 'NR==FNR{if($0~/key value/){split($0,a,"=");sub("^\"","",a[2]);s[x++]=a[2]}}NR!=FNR{xx="\"ref/img/";{sub("URL=.*","URL="xx s[i++],$0);print}
}' file2 file1
<type source="/home/USER/Desktop" Dest="/home/USER/DIR1/Desktop" URL="ref/img/customer/priority"/>
<type source="/home/USER/OP1" URL="ref/img/customer/priority2"/>
<type source="/home/USER/Exe" Dest="/home/USER/DIR1/Exe" URL="ref/img/customer/priority4"/>

1 Like

@ ygemici:
Brilliant . It works . Thanks for the solution. :b:

can you please explain this part?

 s[x++]=a[2]}}NR!=FNR{xx="\"ref/img/";{sub("URL=.*","URL="xx s[i++],$0);print

while read the line we want to get that matches ("key value") from file2 and split it to the parts with '=' and assign to and array that named "a"
[ our line was --> <key value="customer/priority"/> )
so

a[1] -->"    <key value"
a[2] -->""customer/priority"/>"

and works same procedure on the for other matches lines...
and we collect the all a[2] to one array that named "s"

s[0]-->"customer/priority"/>"
s[1]-->"customer/priority2"/>"
s[2]-->"customer/priority4"/>"

and reading the file2 must finish :slight_smile:
and if the NR is equal the FNR so it is read first file,,
else awk start to read other files (second,third,...)
so NR!=FNR is simply means the awk start to reading process from second and other files..
in our issue,we read the second file so it is "file1" remember file arguments

awk ... file2 file1
xx="\"ref/img/" -->  it s just an assing a value.. xx=""ref/img/" (we will add the starting of the new URL value )
sub("URL=.*","URL="xx s[i++],$0)

--> change the URL=.* -->

URL="ref/img/customer/priority"/>
with
URL="xx + s[0]    " ,from our line ($0)
xx->""ref/img/"
s[0]->"customer/priority"/>"
so new URL express --> "URL="ref/img/customer/priority"/>"

we change the URL portion from our line and
print-> print the new line (with new URL)

so every read line (records) means the `i` will increase by one [i\+\+]
finally , works same procedure for the other lines from file1 with s[1] and s[2] values

regards
ygemici

1 Like

Thanks again for detailed explanation.

If lines are not in same order i get wrong output because search is not based on field 2 ( ie /home/USER/Desktop , /home/USER/Exe , /home/USER/OP1 etc )

For example if file2 contains the following:

<path source="/home/USER/Desktop" value="/home/USER/XYZ/Desktop">
    <key value="customer/priority"/>
    <scm tool="toolname/revision"/>
  </path>

<path source="/home/USER/Exe" value="/home/USER/XYZ/ABC/Exe">
    <key value="customer/priority4"/>
    <scm tool="toolname/revision"/>
  </path>

<path source="/home/USER/OP1" value="/home/USER/XYZ/ABC/OP1">
    <key value="customer/priority2"/>
    <scm tool="toolname/revision"/>
  </path>

I get wrong output as :

<type source="/home/USER/Desktop" Dest="/home/USER/DIR1/Desktop" URL="ref/img/customer/priority"/>
<type source="/home/USER/OP1" URL="ref/img/customer/priority4"/> 
<type source="/home/USER/Exe" Dest="/home/USER/DIR1/Exe" URL="ref/img/customer/priority2"/>

Try this:

BEGIN { FS="\""; OFS="\"" }
NR==FNR {
    for (i=1; i<=NF; i++) {
    if ($i ~ "<path source")
        key = $(i+1)
    if ($i ~ "<key value")
        val = $(i+1)
    }
    store[key] = val;
    next;
}
{
    for (i=1; i<=NF; i++) {
    if ($i ~ "<type source")
        key = $(i+1)
        if ($i ~ "URL")
        $(i+1) = "ref/img/" store[key]
    }
    print
} 

save it as e.g. replace.awk and run as

awk -f replace.awk file2 file1
1 Like

ok i modified some :wink:

# awk 'NR==FNR{if($0~/path source/){x=gensub(".*\\/(.*)\">","\\1",$0);getline;split($0,a,"=");sub("^\"","",a[2]);s[x]=a[2]}}
NR!=FNR{for(x in s)if($0~x)sub("URL=.*","URL="xx s[x],$0);print}' xx="\"ref/img/" file2 file1
<type source="/home/USER/Desktop" Dest="/home/USER/DIR1/Desktop" URL="ref/img/customer/priority"/>
<type source="/home/USER/OP1" URL="ref/img/customer/priority2"/>
<type source="/home/USER/Exe" Dest="/home/USER/DIR1/Exe" URL="ref/img/customer/priority4"/>

regards
ygemici

1 Like

Thanks Mirni & ygemici.

Both solutions works.