39

I'm using sed to find and replace patterns within SAS files I have rather than changing them individually. The problem is I am trying to replace macro variables and when I use the ampersand it is not processing correctly.

Here's my code:
sed -ie 's/user=&uid./user=&sysuserid./g' *_table_*.sas

whenever I run this command it seems to append and do all kinds of funky stuff with the original text.

Question: How do I replace text that contains ampersands with sed command?

3
  • 7
    & is a special character so it needs to be escaped when used in the RHS - in your case you have to run 's/user=&uid./user=\&sysuserid./g' although I suspect you also need to escape the dot in the LHS to match a literal dot so you actually need 's/user=&uid\./user=\&sysuserid./g' Jul 18, 2016 at 20:02
  • 1
    yes, '&' on the right basically means "everything that matched on the left", so escape it with '\'. You should make that the answer, rather than just a comment. Jul 19, 2016 at 0:06
  • i didnt have to escape the first period...just a heads up in anyone else was curious :)
    – DukeLuke
    Jul 20, 2016 at 0:50

1 Answer 1

41

& is special in the replacement text: it means “the whole part of the input that was matched by the pattern”, so what you're doing here replaces user=&uidX with user=user=&uidXsysuserid.. To insert an actual ampersand in the replacement text, use \&.

Another thing that looks wrong is that . in the search pattern stands for any character (except a newline), but the . at the end of the replacement text is a literal dot. If you want to replace only the literal string user=&uid., protect the . with a backslash.

sed -e 's/user=&uid\./user=\&sysuserid./g'

If you want to replace any one character and preserve it in the result, put the character in a group and use \1 in the replacement to refer to that group.

sed -e 's/user=&uid\(.\)/user=\&sysuserid\1/g'

In fact, given the repetition between the original text and the replacement, you should use groups anyway:

sed -e 's/\(user=&\)u\(id\.\)/\1sysuser\2/g'

i.e. “replace u by sysuser between user=& and id.”.

7
  • could you explain groups?
    – DukeLuke
    Jul 20, 2016 at 0:53
  • 2
    @lucasdavis500 A group identifies a part of the pattern. It's delimited by backslash-parentheses. For example \(user=&\) is a pattern that matches user& and stores the match string as a group (group number 1 since it's the first group in the pattern). Then in the replacement \1 is replaced by the string stored for group number 1. Jul 20, 2016 at 0:57
  • do you mean (user=&) stores user=&, not user&?
    – DukeLuke
    Aug 17, 2016 at 12:40
  • @lucasdavis500 I don't understand your comment. The character = in regular expressions and in replacement text stands for itself, so user=& matches only user=&, and user=& in the replacement text yields user= followed by the part of the line matched by the regex. Aug 17, 2016 at 13:27
  • 1
    @lucasdavis500 The = character does not have any special meaning. user=& in the replacement text produces user= followed by the original matched text. user=\& in the replacement text produces user=& Aug 18, 2016 at 18:15

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.