0

I have two big files. file1 has data in below format

place u_RX_WR_SE1_LS { } R0 -place
place u_bank_LS { } R0 -place 

file2 has data in below format

set inst RX_WR_SE1_PD ; add -inst $inst -cell PR ; place $inst  5.76    5305.84 0
set inst RX_WR_SE2_PD ; add -inst $inst -cell PR ; place $inst  5.76    5338.864    0
set inst bank_PD ;  add -inst $inst -cell PR ; place $inst  5.76    5371.888    0

I want to search 2nd field removing starting u_ and _LS from file1 i.e RX_WR_SE1 in file2, and if found in file2, for same match line copy field $13 $14 from file2 and add it inside { } in file1.

The output should be in below format.

place u_RX_WR_SE1_LS { 5.76 5305.84 } R0 -place
place u_bank_LS { 5.76  5371.888 } R0 -place 

Anyone who can help using TCL or SHELL? In shell I tried

awk 'FNR==NR{gsub(/u_|_LS/,"",$2);arr[$2]="";next} 
{
for (i in arr) { if ($0 ~ i) {print i,$13,$14}}
}
' file1 file2

but this is not giving proper results .

In TCL it is also fine.

Shreya
  • 639
  • 4
  • 11

3 Answers3

1

You may have solved it for yourself but if you are still waiting for an answer, would you please try the following:

awk '
    NR==FNR {
        f2 = $2                         # backup $2 to avoid modification
        gsub(/u_|_LS/, "", f2)          # remove u_ and _LS from f2
        arr[f2] = $0                    # associate f2 to the line
        next
    }
    {
        for (i in arr) {
            if ($0 ~ i) {
                sub(/\{[[:blank:]]+\}/, "{ " $13 " " $14 " }", arr[i])
                                        # fill curly braces of arr[i] with $13 and $14
                print arr[i]
            }
        }
    }
' file1 file2

Output:

place u_RX_WR_SE1_LS { 5.76 5305.84 } R0 -place
place u_bank_LS { 5.76 5371.888 } R0 -place 
tshiono
  • 21,248
  • 2
  • 14
  • 22
  • This is very neat and simple `awk` code, thanks for sharing, cheers. IMHO `[[:blank:]]` is needed here? OR we can use `[[:space:]]` here, just a thought. – RavinderSingh13 Sep 13 '22 at 04:54
  • 1
    Thank you for the comment! Actually I can't decide well which regex will be appropriate to express something between the curly braces. `[[:blank:]]*` might be better? Btw you may be interested in my answer to another question [here] (https://stackoverflow.com/a/73615334/8572380). BR. – tshiono Sep 13 '22 at 05:49
  • Hey buddy that was just a thought, your code looks good, honestly I too get confuse many times so was trying to get your thoughts on this one. On other question yes I saw that but to me it was not clear so I didn't answer on it cheers – RavinderSingh13 Sep 13 '22 at 05:55
  • 1
    @RavinderSingh13 The provided string `{ }` looks containing a whitespace in between, but I'm not sure whether the count is always one and it is or not another blank character. In such a case I would pick `\s+` but `awk` does not support the short-hand and I'd use `[:blank:]` or `[:space:]`. As you know, `[[:blank:]]` is equivalent to `[ \t]` and `[[:space:]]` is to `[ \t\r\n\v]`. Then I just thouht `[[:blank:]]+` might better. Hope I'm answering your question. – tshiono Sep 13 '22 at 06:20
  • 1
    @RavinderSingh13 As for another question, I thouht it is a good example of `recursive regex`, which is suitable for parsing recursive syntaxes such as `function call`. – tshiono Sep 13 '22 at 06:21
  • Thank you buddy for clarifying it, yeah for other question you are right – RavinderSingh13 Sep 13 '22 at 06:24
0

I dont see any Trim or Matching conditions in your Code.

Try this,

`

awk 'FNR==NR{gsub(/u_|_LS/,"",$2);arr[$2]="";next} 
{
for (i in arr) { if ($0 ~ i) {print i,$13,$14}}
}
' file1 file2

`

RX_WR_SE1 5.76 5305.84
bank 5.76 5371.888

gsub performs the Trim for your text, so as to match with the next file for loop performs the matching.

It's not fully up to your expectations of the output, but I believe it provides a base for you.

VipinKG
  • 11
  • 3
  • This code is fine but while making changes in file1, ```u_ and _LS``` are gone. only while searching it should not be there but while writing field 13 and14 in file1 no modifications should be there in file1. – Shreya Sep 09 '22 at 11:26
  • The above code is fine, but one issue is , suppose we have ```u_LNA_PD``` for this code will do properly but if we have ```u_LNA_XYZ_PD``` for this also script is searching for ```LNA``` in ```arr``` which is not true it should search for complete ```LNA_XYZ```. @VipinKG – Shreya Sep 11 '22 at 09:02
0

With Tcl

# extract the data from file2
set fh [open file2]
set values {}
while {[gets $fh line] != -1} {
    set fields [regexp -all -inline {\S+} $line]
    set inst_name [regsub -- {_PD$} [lindex $fields 2] ""]
    dict set values $inst_name [lrange $fields 12 13]
}
close $fh

# read file1, replace the values, and store in a new file
set fin [open file1]
set fout [open file1.new w]
while {[gets $fin line] != -1} {
    set inst_name [regsub {^u_(.+)_LS$} [lindex [split $line] 1] {\1}] 
    puts $fout [format {place %s {%s} R0 -place} $inst_name [dict get $values $inst_name]]
}
close $fin
close $fout

# move the new contents to file1
# remove next line if you don't need to backup the file
file link -hard file1 file1.bak
file rename -force file1.new file1 
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • The above code is working fine, but again its giving output as ```place RX_WR_SE1 { 5.76 5305.84 } R0 -place place bank { 5.76 5371.888 } R0 -place``` again ```u_ and _LS``` are missing from output – Shreya Sep 11 '22 at 08:44
  • $inst_name is overwritting the previous one but again while ```regsub``` its not considering ```u_ and _PD```?? @glenn jackman . change whch is working fine ```puts $fout [format {place %s {%s} R0 -place} u_$inst_name\_PD [dict get $values $inst_name]]``` – Shreya Sep 11 '22 at 09:06