0

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>

Or:

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.)

2 Answers 2

1
  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/  };
  /^$/d
' ~/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/ }
4
  • Doesn't this involve several expressions instead of just two? Is this more or less efficient?
    – 2rs2ts
    Jul 16, 2013 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, 2013 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, 2013 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, 2013 at 22:22
1

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.

1
  • 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, 2013 at 21:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .