0

I have a string which I want to replace. It is of the format:

  VAL1          = "D_AC" ,
  VAL2          = "DRC" ,
  VALX2         = 3.33330000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 

Note that the string has both double quotes and newline characters.

I want to replace it with another string:

  VAL1          = "D_AC" ,
  VAL2          = "DRC" ,
  VALX2         = 2.22110000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 

Ive tried:

export OLD_STRING1="  VAL1          = \"D_AC\" ,"
export OLD_STRING2="  VAL2          = \"DRC\" ,"
export OLD_STRING3="  VALX2         = 3.33330000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, "

export NEW_STRING1="  VAL1          = \"D_AC\" ,"
export NEW_STRING2="  VAL2          = \"DRC\" ,"
export NEW_STRING3="  VALX2         = 2.22110000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, "

Then called grep and sed as so:

find . -type f -name '*filename*' -exec sed -i '' s/$OLD_STRING1$OLD_STRING2$OLD_STRING3/$NEW_STRING1$NEW_STRING2$NEW_STRING3/ {} +

sed generates an error:

sed: 1: "s/BX2          = "D_AC ...": unterminated substitute pattern

How could I resolve this?

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
newkid
  • 1,368
  • 1
  • 11
  • 27
  • Consider broadening your solution set to perl. As I recall, perl had ready support for this sort of thing. – Mark Jan 26 '19 at 18:21
  • The first 2 lines in the strings are the same. Are you trying to change `VALX2`, but only after the matches of `VAL1` and `VAL2` ? – Walter A Jan 26 '19 at 23:07
  • This occurs when the script-string is malformed. This is because you didn't properly quote the script-string. You likely didn't use quotes because you wanted bash to apply variable substitution which could be done by alternating a series of single and double quotes where appropriate. Once this is done and sed does properly execute, this is not to say that it will succeed. Anyway, besides that, I find your question-code contradictory with the question-title, where's the spanning multi-line issue? In this case, you can use sed, perl, or w/e. sed is my go-to for this problem, using `N` to buffer. – Rafael Jan 27 '19 at 02:27

1 Answers1

1

This would be a nightmare to try to do robustly and portably with sed since sed doesn't understand literal strings (see Is it possible to escape regex metacharacters reliably with sed).

Given this input where you want to change file such that the text contained in old becomes the text contained in new:

$ cat old
  VAL1          = "D_AC" ,
  VAL2          = "DRC" ,
  VALX2         = 3.33330000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
$
$ cat new
  VAL1          = "D_AC" ,
  VAL2          = "DRC" ,
  VALX2         = 2.22110000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
$
$ cat file
foo
  VAL1          = "D_AC" ,
  VAL2          = "DRC" ,
  VALX2         = 3.33330000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
bar

and this script:

$ cat tst.awk
FILENAME==ARGV[1] { old=$0; next }
FILENAME==ARGV[2] { new=$0; next }
s=index($0,old) {
    $0 = substr($0,1,s-1) new substr($0,s+length(old))
}
{ print }

it's this simple:

$ awk -v RS= -f tst.awk old new file
foo
  VAL1          = "D_AC" ,
  VAL2          = "DRC" ,
  VALX2         = 2.22110000e+04, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
bar
Ed Morton
  • 188,023
  • 17
  • 78
  • 185