I'm reading the RealName from dscl for various users. Depending on the user, the output can be one of the following two:

RealName: <name>



So I have sed -e 's|^[RealName:[:space:]]*||g' -e '/^$/d' to get just the <name> in either case. I'm new to regular expressions, so I'm having trouble merging the two expressions. Any suggestions? (Just doing it for fun. That command works just fine as-is.)

  1. Match a line that has only RealName: and spaces, append the Next line to the pattern space.
  2. remove RealName: and the newline.
  3. What's left, should be <name>

Since the command order matters, the next select-lines command that matches anything ((.*)) on a line that starts with RealName: will have "something interesting" after the matched regex.

  1. Match all other lines starting with RealName: and do the same without newlines
  2. delete empty lines.

sed -E -e '
  /^RealName:\s*$/{ N; s/RealName:.*\n//  }; 
  /^RealName:(.*)/{ s//\1/  };
' ~/tmp/RealName

If the substitute command has nothing in the match field, it defaults to the previous select-lines command's regex.

/hello world/{ s//bye mars/ }    
/hello world/{ s/hello world/bye mars/ }
  • Doesn't this involve several expressions instead of just two? Is this more or less efficient? – 2rs2ts Jul 16 '13 at 21:52
  • 1
    If by expression you mean arguments to the -e option, then this answer merges two separate expressions into one with three commands. I used two separate expressions for Realname: <foo> vs Realname:\n<foo> because it's easier to demonstrate, write and remember. And what matters efficiency, I guess appending _N_ext line is "slow". But ^RealName\s*$ should be less expensive to match than than [:NRaelm\ ]*. So overall it should be faster. – Ярослав Рахматуллин Jul 16 '13 at 22:05
  • Got it. Thanks for the breakdown into what this does. I guess what I meant was semicolon delimited parts of the expression, not multiple -e options. It's more verbose but if it's more efficient then that's great. – 2rs2ts Jul 16 '13 at 22:18
  • 1
    sed is very fast in general. You don't need to worry about efficiency unless your input is very (gigabytes) large. – Ярослав Рахматуллин Jul 16 '13 at 22:22

It's not a lot shorter, but you could just do

sed -e 's|^[RealName:[:space:]]*||g;/^$/d'

the semicolon makes it a separate expression, but you really want to catch a multiline pattern, which is probably not as nice as what you have here, but this is a good resource.

  • Thanks for the link. Can't make heads or tails of it, though; I'm just starting with regex and unfortunately the command the author wrote is way too complex for me. – 2rs2ts Jul 16 '13 at 21:51

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.