1

I need help with replacing a string in a file where "from"-"to" strings coming from a given file.

fromto.txt:

"TRAVEL","TRAVEL_CHANNEL"
"TRAVEL HD","TRAVEL_HD_CHANNEL"
"FROM","TO"

First column is what to I'm searching for, which is to be replaced with the second column.

So far I wrote this small script:

while read p; do
  var1=`echo "$p" | awk -F',' '{print $1}'`

  var2=`echo "$p" | awk -F',' '{print $2}'`
  echo "$var1" "AND" "$var2"

  sed -i -e 's/$var1/$var2/g' test.txt
done <fromto.txt

Output looks good (x AND y), but for some reason it does not replace the first column ($var1) with the second ($var2).

test.txt:

"TRAVEL"

Output:

"TRAVEL" AND "TRAVEL_CHANNEL"
sed -i -e 's/"TRAVEL"/"TRAVEL_CHANNEL"/g' test.txt
"TRAVEL HD" AND "TRAVEL_HD_CHANNEL"
sed -i -e 's/"TRAVEL HD"/"TRAVEL_HD_CHANNEL"/g' test.txt
"FROM" AND "TO"
sed -i -e 's/"FROM"/"TO"/g' test.txt

$ cat test.txt
"TRAVEL"
Adrian
  • 2,576
  • 9
  • 49
  • 97
  • 1
    To get you started, `sed -i` will work on a file in-place. Now you just need to figure out the commands for `sed` :) – bedwyr Dec 29 '17 at 21:07
  • Yes, I can add sed command before each line, but the actual "fromto.txt" is quite big. It is somehow possible to read these variables/arguments for sed from a file? – Adrian Dec 29 '17 at 21:09
  • That's a helpful clarification -- it isn't immediately obvious from the description. So as a simple recipe (this can be done from the shell prompt): 1. for each line in the file; 2. split the line, extracting the values between the '"'; 3. use those values in a `sed` command for replacement (e.g. `sed -i 's/$val1/$val2/g'`). Does that make sense? – bedwyr Dec 29 '17 at 21:13
  • You can use sed to create a sed script from the replacement file and then use that for a `sed - f` call. – daniu Dec 29 '17 at 21:26
  • This gave me some inspiration, I updated the main question. :) – Adrian Dec 29 '17 at 21:48
  • Why use `awk` instead of `IFS=, read var1 var2`? – Barmar Dec 29 '17 at 22:03
  • 1
    Variables aren't expanded inside single quotes, only double quotes. – Barmar Dec 29 '17 at 22:04
  • Yes! I used single quotes in sed, I replaced with double quotes: sed -i -e "s/$var1/$var2/g" test.txt and works now, great. Thank you for the help. – Adrian Dec 29 '17 at 22:09

2 Answers2

1

input:

➜  cat fromto
TRAVEL TRAVEL_CHANNEL
TRAVELHD TRAVEL_HD
➜  cat inputFile
TRAVEL
TRAVELHD

The work:

   ➜  awk 'BEGIN{while(getline < "fromto") {from[$1] = $2}} {for (key in from) {gsub(key,from[key])} print}' inputFile > output

and output:

➜  cat output
TRAVEL_CHANNEL
TRAVEL_CHANNEL_HD
➜  

This first (BEGIN{}) loads your input file into an associate array: from["TRAVEL"] = "TRAVEL_HD", then rather inefficiently performs search and replace line by line for each array element in the input file, outputting the results, which I piped to a separate outputfile.

The caveat, you'll notice, is that the search and replaces can interfere with each other, the 2nd line of output being a perfect example since the first replacement happens. You can try ordering your replacements differently, or use a regex instead of a gsub. I'm not certain if awk arrays are guaranteed to have a certain order, though. Something to get you started, anyway.

2nd caveat. There's a way to do the gsub for the whole file as the 2nd step of your BEGIN and probably make this much faster, but I'm not sure what it is.

zzxyz
  • 2,953
  • 1
  • 16
  • 31
  • 1
    Great one liner, but the format of fromto is more or less fixed. There are quotes used, because of strings with space, example "DISCOVERY CHANNEL". – Adrian Dec 29 '17 at 22:01
  • 1
    @Adrian - Ah, I think that can be solved with `patsplit()` and something like from here: https://www.gnu.org/software/gawk/manual/gawk.html#Splitting-By-Content but we're approaching a reasonable limit on one-liners (and my skill with awk), I think :) – zzxyz Dec 29 '17 at 22:21
0

you can't do this oneshot you have to use variables within a script

maybe something like below sed command for full replacement

-bash-4.4$ cat > toto.txt
1
2
3
-bash-4.4$ cat > titi.txt
a
b
c
-bash-4.4$ sed 's|^\s*\(\S*\)\s*\(.*\)$|/^\2\\>/s//\1/|' toto.txt | sed -f - titi.txt > toto.txt
-bash-4.4$ cat toto.txt
a
b
c
-bash-4.4$ 
francois P
  • 306
  • 6
  • 20