2

I am trying to replace strings found in File1 with strings in File2

File1

<IMG SRC="/Repository/GetImage.dll?baseHref=Orange/2011/03/27&amp;EntityID=Ad12911&amp;imgExtension=" />
<IMG SRC="/Repository/GetImage.dll?baseHref=Orange/2011/03/20&amp;EntityID=Ad13304&amp;imgExtension=" />
<IMG SRC="/Repository/GetImage.dll?baseHref=Orange/2010/08/29&amp;EntityID=Ad13724&amp;imgExtension=" />

File2

/getimage.dll?path=Orange/2011/03/27/129/Img/Ad1291103.gif
/getimage.dll?path=Orange/2011/03/20/133/Img/Ad1330402.gif
/getimage.dll?path=Orange/2010/08/29/137/Img/Ad1372408.gif

When I run this command

$ sed -e 's/.*SRC="\/Repository\([^"]*\)".*/\1/p{r File1' -e 'd}' File2

I get this error

sed: 1: "s/.*SRC="\/Repository\( ...": bad flag in substitute command: '{'

Is there something wrong with my regex?

The result I am trying to achieve would be to have File1 look like:

File1

<IMG SRC="/Repository/getimage.dll?path=Orange/2011/03/27/129/Img/Ad1291103.gif" />
<IMG SRC="/Repository/getimage.dll?path=Orange/2011/03/20/133/Img/Ad1330402.gif" />
<IMG SRC="/Repository/getimage.dll?path=Orange/2010/08/29/137/Img/Ad1372408.gif" />
5
  • 2
    It would be more useful if you provide an example of the result you expect from this command. Commented Oct 13, 2014 at 12:14
  • 1
    I am not sure sed can fetch/join line in/from another file.
    – Archemar
    Commented Oct 13, 2014 at 12:22
  • The regex portion is OK (I think) - however I don't see how the command portion can work. At best, the r command will read the whole of File1 into pattern space each time (and can't be used within a substitute command, as you appear to be trying to do). Commented Oct 13, 2014 at 12:37
  • @geedoubleya thanks, I added the result I would like to see in File1.
    – rbroadus
    Commented Oct 13, 2014 at 21:23
  • @Archemar, I was using this question as a guide and they replace the contents of one file with another: unix.stackexchange.com/questions/20322/…
    – rbroadus
    Commented Oct 13, 2014 at 21:25

3 Answers 3

3

If you are trying to replace in File1 everything inside double quotes with new image names taken from File2 then I would use awk:

awk -F'"' 'NR==FNR{a[i++]=$1;next}{print $1 FS a[j++] FS $3}' File2 File1

The output is the following:

<IMG SRC="/getimage.dll?path=Orange/2011/03/27/129/Img/Ad1291103.gif" />
<IMG SRC="/getimage.dll?path=Orange/2011/03/20/133/Img/Ad1330402.gif" />
<IMG SRC="/getimage.dll?path=Orange/2010/08/29/137/Img/Ad1372408.gif" />
3
  • Here is the actual File1 that I am trying to copy image URLs into: pastebin.com/XbwtZJPa. When I run the awk command I get double quotes at the beginning of each line.
    – rbroadus
    Commented Oct 13, 2014 at 21:38
  • Thanks! Given the example files I provided this answer worked, so I marked it as the solution. However, I did have an issue running this awk command with the file in my pastebin link. Would it be best to ask about this file in a separate question?
    – rbroadus
    Commented Oct 13, 2014 at 21:57
  • @rbroadus I'm just looking at pastebin file, but the format of that file is completely different - first of all in your example you have only <img> lines, so all lines should be replaced (and that is the solution in my answer), but in real life you have to somehow define which lines you want to replace under which circumstances. So yes, it would be best if you post new question and please describe precisely what exactly do you want to achieve.
    – jimmij
    Commented Oct 13, 2014 at 22:06
1

I have no idea what you're trying to do there but then my sed-fu is not that strong so I guess you're using some arcane syntax I am unaware of. Since I can't tell you what's wrong with your sed (but an educated guess is that the special characters contained in your replacement strings (/,? etc) are causing problems), I will instead offer a perl alternative:

perl -i -pe 'BEGIN{open($f,shift); while(<$f>){chomp; push @F,$_}}
            $k=shift(@F); s/(.*SRC=.)([^"]*)/$1$k/' file2 file1 

Here's the same thing written as a commented script to make it clearer. In the one-liner above, the -i causes the actual input file to be changed, just like sed -i.

#!/usr/bin/env perl

## This is the equivalent of the BEGIN{} block.
## @ARGV is the array of arguments and shift returns
## the first element of it. This is file2 which is
## then opened, each line is read, its trailing \n
## is removed by chomp and it is then added to the @F array.
my $file=shift(@ARGV);
open($f,$file);
while(<$f>){chomp; push @F,$_}

## This is the rest of the oneliner above. The -pe options
## cause the file to be read and each line printed after 
## the script is applied. Since the previous block removed 
## file2 from @ARGV, this is applied to file1 only.
while (<>) {
    ## Remove the 1st item of @F. This is a line of file2.
    $k=shift(@F);

    ## Make the substitution. The \ before the " is not 
    ## needed, I just added it here because otherwise, the 
    ## syntax highlighting is broken. 
    s/(.*SRC=.)([^\"]*)/$1$k/;
    ## This print is implied by the -p flag
    print;
}
0

The error is telling you that your sed command is wrong, not your regexp. You need a newline or semicolon to separate the s command from the following { command. Equivalently, you can put them in separate -e arguments.

sed -e 's/.SRC="/Repository([^"])".*/\1/p' -e '{' -e 'r File1' -e 'd' -e '}' File2

This won't do what you want, though. It removes the prefix …SRC="Repository/ and the part starting at the next double quote from the input, printing only lines that have been replaced (because of the p flag on the s command, and the following d), and it inserts a copy of File1 for each input line (matched or not).

If you want to match data from the two files, you'll need a more powerful tool than sed¹. Awk or Perl are good choices.

¹ Technically, sed is Turing complete, but doing that in sed would be extremely complex and obscure.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .