0

This was previously asked at the below url, but only done using the a forward-slash as the delimiter. https://stackoverflow.com/a/11245501/2520289

What is the proper syntax to do the exact same thing but with any of the other compatible delimiters for sed?

I have the delimiter changed for universal compatibility across most bash environments. (git-bash/any linux)

For example, I am currently doing the below snippet to replace any matches of the specific string but not the whole line.

function misc_findReplace()
{
    VARIABLE_FIND="$1"
    VARIABLE_REPLACE="$2"
    VARIABLE_FILE="$3"

    echo "Finding: $VARIABLE_FIND"
    echo "Replacing With: $VARIABLE_REPLACE"
    echo "File to Operate On: $VARIABLE_FILE"

    sed -i "s@${VARIABLE_FIND}@c${VARIABLE_REPLACE}@g" "$VARIABLE_FILE"
}

FILE_TO_WORK_WITH="/path/to/my/file.properties"

STRING_TO_FIND="destination_hostname=<destination_hostname>"
STRING_TO_REPLACE="destination_hostname=localhost"
misc_findReplace "$STRING_TO_FIND" "$STRING_TO_REPLACE" "$FILE_TO_WORK_WITH"
Cody
  • 127
  • 1
  • 10
  • 1
    I'm no `sed` expert but I think `/` is a command, not a delimiter (as it is in the `s/foo/bar/` construct). So you probably can't change it, but there's probably a way to escape any slashes that occur in your search string. – Thomas Sep 10 '20 at 14:22
  • 1
    You have to escape the first delimiter: `\@address@c something`, and you can't use flags for the `c` command. There is no third delimiter. – Benjamin W. Sep 10 '20 at 14:24
  • See https://stackoverflow.com/q/5864146/3266847 – Benjamin W. Sep 10 '20 at 14:24
  • @Thomas - try the above function, somewhere along the line in the past year and a half I gathered this sed expression from other research and it works properly without the usage of slash - aka makes it compatible with git-bash annoying path conversion concepts and most versions of bash execution environment. – Cody Sep 10 '20 at 14:50
  • Yes, but the above function is using the `s` command whereas the question you linked to uses the `/` command. – Thomas Sep 10 '20 at 14:51
  • @Thomas, each time I've read the man page for sed and the expressions that back it up, I get very lost and have yet to find a decent article that breaks it all down a bit at a time. My above example is something I found a long while back (tested extensively) and held on to for safe keeping so I never had to rewrite it. – Cody Sep 10 '20 at 16:59

2 Answers2

2

To use different delimiters in sed, you want to escape the first occurance with a backslash. such, the correct command would be sed -i "\@${VARIABLE_FIND}@c${VARIABLE_REPLACE}" "$VARIABLE_FILE"

stas chern
  • 61
  • 6
  • 1
    To limit the risk of collision with the delimiter, you can use the ASCII FS character like this `FS=$'\37'; sed -i "\\$FS$VARIABLE_FIND${FS}c$VARIABLE_REPLACE$FSg" "$VARIABLE_FILE"` – Léa Gris Sep 10 '20 at 14:33
  • Hey thanks for that tidbit - I forgot to add the escape character that was in the original working function before I made this post - was doing experimentation prior to try and get the other stackoverflow answer working – Cody Sep 10 '20 at 14:48
  • 1
    @stas-chernetski - your solution worked, but had to remove the @g off the end of it. I'll mark your answer as the solution if you make that modification. – Cody Sep 10 '20 at 16:39
  • For anyone that is interested in the full script see link - https://garrett.ms/2020/09/10/bash-find-replace-whole-line-based-on-partial-match/ – Cody Sep 10 '20 at 16:50
  • thanks for pointing out! had a muscle memory on @g at the end of sed. – stas chern Sep 10 '20 at 17:29
1

If I understand your question correctly, you have some text in a variable VARIABLE_FIND which may contain slashes, and you want to replace all lines that contain that text by $VARIABLE_REPLACE.

This sed command will do that:

sed -i "/${VARIABLE_FIND//\//\\/}/c\\${VARIABLE_REPLACE}" "$VARIABLE_FILE"

It uses the same commands as in the answer you linked to but first escapes $VARIABLE_FIND by replacing each / character by \/.

The way that's done is with bash's construct ${var//search/replace}, plus some extra backslashes for escaping inside double quotes.

Demo:

$ VARIABLE_FIND=/foo/
$ VARIABLE_REPLACE=This line has been replaced
$ echo -e 'some/foo/line\nsome/bar/line' | sed "/${VARIABLE_FIND//\//\\/}/c\\${VARIABLE_REPLACE}"
This line has been replaced
some/bar/line
Thomas
  • 174,939
  • 50
  • 355
  • 478
  • Thank you for your answer. Sed supports different delimiters but the scope of support for different expression style, I'm not sure really. Based on @stas answer from above, his answer vs your answer, would his replace only the first occurrence or all with the knowledge you have of expressions? – Cody Sep 10 '20 at 21:02