Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

awk string substituion exception 2

Status
Not open for further replies.

pdtak1

Technical User
Mar 29, 2016
6
0
0
US
Hello awk experts, I want to substitute the data.txt file according to the template.txt file rules:

template.txt contains the following:
hello hola
one uno
two dos
three tre
four quatro
...
...
goodbye adios


data.txt contains the following:
hello my name is David
one of my friends are John
/two three
hello my number two friend is Mark
...

substituted.txt contains:
hola my name is David
uno of my friends are John
/dos tres
hola my number dos friend is Mark
...

I got this command to work:
awk 'NR==FNR {a[$1]=$2;next} {for ( i in a ) gsub(i,a)}1' templates.txt data.txt > substituted.txt

But I want to skip the string that starts with "/" to NOT substitue (ie. remain as /two) so I added the !/^\//
awk 'NR==FNR {a[$1]=$2;next} {for ( i in a ) !/^\//; gsub(i,a)}1' templates.txt data.txt > substituted.txt

Now, this command doesn't substitue at all now. What am I doing wrong?

Any help is greatly appreciated. Thank you!
 
Hi

pdtak1 said:
What am I doing wrong?
[tt]for[/tt] executes the [highlight]first command[/highlight] that follows it :
Code:
[teal]{[/teal][b]for[/b] [teal]([/teal] i [b]in[/b] a [teal])[/teal] [highlight][teal]![/teal][fuchsia]/^\//[/fuchsia][/highlight][teal];[/teal] [b]gsub[/b][teal]([/teal]i[teal],[/teal]a[teal][[/teal]i[teal]])}[/teal]

The easiest fix is to tell to execute [tt]gsub()[/tt] only if the match was successful :
Code:
[teal]{[/teal][b]for[/b] [teal]([/teal] i [b]in[/b] a [teal]) ![/teal][fuchsia]/^\//[/fuchsia] [highlight pink][teal]&&[/teal][/highlight] [b]gsub[/b][teal]([/teal]i[teal],[/teal]a[teal][[/teal]i[teal]])}[/teal]


Feherke.
feherke.ga
 
Thank you feherke!
One more question, now if I only want to substitute the 4th field of the data.txt file (ignore the first 3 fields), then where would I tell it to check only the 4th field (or ignore the first 3 fields)?
 
Hi

[tt]gsub()[/tt] can take a 3[sup]rd[/sup] parameter, a variable to process. By default is [tt]$0[/tt]. If you want to process only [tt]$4[/tt], just tell it :
Code:
[teal]{[/teal][b]for[/b] [teal]([/teal] i [b]in[/b] a [teal]) ![/teal][fuchsia]/^\//[/fuchsia] [teal]&&[/teal] [b]gsub[/b][teal]([/teal]i[teal],[/teal]a[teal][[/teal]i[teal]][/teal][highlight][teal],[/teal][navy]$4[/navy][/highlight][teal])}[/teal]

Feherke.
feherke.ga
 
feherke,

I'm still having issues skipping the first column
{for ( i in a ) !/^\// && gsub(i,a)} didn't work.

I want to skip the first column but substitue all remaining columns... can't get it working.

awk 'NR==FNR {a[$1]=$2;next} {for ( i in a) gsub(i,a,!$1); printf $1}1'
awk 'NR==FNR {a[$1]=$2;next} {for ( i in a ) !/^\// && gsub(i,a)}; printf $1}1'

None give me the results I want... skip the first column, then substitute remaining columns.
Please help.
 
Hi

I am afraid I did not understood you correctly. Actually you want to replace all matching strings excepting those prefixed with slash ( / ) ?
Code:
one uno
two dos
Code:
one \two three \one two three
Code:
uno \two three \one dos three

Well, this is more complicated as Awk regular expressions does not handle negative look-behind assertion.

The simplest workaround is to temporarily [highlight]replace the slash prefixed occurrences to something else[/highlight] ( something you are sure is not present in your text - here I use the string "--KEEP--" ), then replace the remaining, un-prefixed occurrences, then [highlight pink]replace that placeholder back[/highlight] :
Code:
[teal]{[/teal][b]for[/b] [teal]([/teal] i [b]in[/b] a [teal]) {[/teal][highlight][b]gsub[/b][teal]([/teal][i][green]"/"[/green][/i]i[teal],[/teal][i][green]"--KEEP--"[/green][/i][teal])[/teal][/highlight][teal];[/teal] [b]gsub[/b][teal]([/teal]i[teal],[/teal]a[teal][[/teal]i[teal]]);[/teal] [highlight pink][b]gsub[/b][teal]([/teal][i][green]"--KEEP--"[/green][/i][teal],[/teal][i][green]"/"[/green][/i]i[teal])[/teal][/highlight][teal]}}[/teal]

Please note that your original code also transforms for example "bayonet" to "bayunot", which is done by the modified code too. Not sure if that was your intention or not.


Feherke.
feherke.ga
 
Wow, that worked perfectly!
Thank you so much!
You're the best feherke!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top