17

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?

  • 6
    & 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' – don_crissti Jul 18 '16 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. – Edward Falk Jul 19 '16 at 0:06
  • i didnt have to escape the first period...just a heads up in anyone else was curious :) – lucasdavis500 Jul 20 '16 at 0:50
21

& 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.”.

  • could you explain groups? – lucasdavis500 Jul 20 '16 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. – Gilles Jul 20 '16 at 0:57
  • do you mean (user=&) stores user=&, not user&? – lucasdavis500 Aug 17 '16 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. – Gilles Aug 17 '16 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=& – Gilles Aug 18 '16 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.