3

I have the following line to execute in a script and that delete two lines above it. But now my $TEST variable contain values like '/DATA/test10' and my variable ID contain '10'. How can i use this with sed?

sed -i ":a;N;s/\n/&/2;Ta;/path = $TEST\/$ID/s/.*//;P;D" /collection.txt

migrated from serverfault.com Nov 25 '15 at 14:35

This question came from our site for system and network administrators.

5

If you simply want to treat a string as a literal in sed there's already an answer for that:

escaped_testx="$(sed -e 's/[\/&]/\\&/g' <<< "$TEST"; echo x)"
escaped_test="${escaped_testx%x}"

The extra x is to be able to handle trailing newlines, which would otherwise be removed by the command substitution.

2

Using / as the separating character for the sed s command is not mandatory. The separator is the first character after the s. You can use | or # or (almost) anything you like. For things with lots of / characters, like file name paths, I like to use commas because they go under the baseline and are thus easier to see, while being very rare in filenames:

sed 's,^/home/me/subdir/,^/home/he/otherdir/,'

Choose a character you won't find in your search and replace. If you do have one or two, prefix them with backslash.

  • I just looked closer at your sed commands and I see that your variables are not in the s command per se, but in the search filter. I think your best option would be to escape your variables as described by l0b0, or do a prior global replace (using tr) of / by some other character guaranteed not to be in your file, and then tr it back the other way after your sed is done. Or rewrite everything in perl, of course. – Law29 Nov 21 '15 at 17:41
  • But your proposed alternatives to the / character could also be showing up in the variable. – kasperd Nov 21 '15 at 17:46
  • @kasperd Most of the time one knows some character that cannot or DOES not exist in the input. If that is not the case, see my comment about escaping. – Law29 Nov 22 '15 at 14:22
0

In regular expressions you can escape characters by prepending a backslash.

So / becomes \/.

This will make your regex look hidious (s/\/home\/stuff\/dir1/\/home\/stuff/) but it works!

  • 1
    yes, but I cannot change variable $TEST. I have to use it as it is. so if the variable contain more than two '/' how can I escape it? – Vishnu Nov 21 '15 at 11:17
  • @Vishnu Replace all / with a pipe |, it does not need to be a forward slash that delimits the regex – x13 Nov 21 '15 at 20:23
  • yes I understand your point, but the $TEST contain a string and that string I cannot change. So I cannot add '\' infront of all the '/' inside the text string. I can use the above answer as suggested by l0b0 . – Vishnu Nov 22 '15 at 5:12
0

If you want to avoid actually modifying the value of your variable, you can just stream it:

printf "%s\n" "$PATH/$ID"   |
sed   -e's|[]$/.\^[]|\\&|g' \
      -e's|.*|/path = &/g|' |
sed   -e':a;N;s/\n/&/2;Ta' -f- -eP\;D /collection.txt

It assumes neither variables can contain a newline. It also makes an assumption about:

/path = $TEST\/$ID/s/.*//

...which is that you just want to clear the line. You can just use get to overwrite pattern space with your blank hold space - (at least, it will be blank in this script as it isn't otherwise used in your example). You might also use zap in a GNU sed to achieve the same thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.