Results 1 to 8 of 8

Thread: Help wanted to understand the "g" command in sed

  1. #1
    Join Date
    Dec 2007
    Location
    Bombay
    Beans
    5,532
    Distro
    Lubuntu 14.04 Trusty Tahr

    Help wanted to understand the "g" command in sed

    I made these two small files:
    a1.txt
    this is the first line
    this is the second line
    there are two lines above this one
    and
    a2.txt
    this is line a
    this is line b
    lines a and b are above this one

    Then, to recover just the lines from each file containing "above", I can use:
    Code:
    sed -nrs '/above/p' a*.txt
    To introduce blank lines below each of the lines, I can use:
    Code:
    sed -nrs '/above/p;${g;p}' a*.txt
    I want help to understand the function of g in the second code.
    I looked at info sed and it has this to say about g:
    "Replace the contents of the pattern space with the contents of the hold space."

    My understanding is that each line is stored in the "pattern space" and then processed by the specified commands, but at what point does the "hold space" figure and how does that end up providing a blank line?

    Basically, what does "${g;p}" do? I know it works. But how?
    Last edited by vasa1; March 18th, 2013 at 04:52 PM. Reason: marked as [SOLVED]
    de gustibus et coloribus non est disputandum -- Wiktionary

  2. #2
    Join Date
    Apr 2012
    Beans
    5,169

    Re: Help wanted to understand the "g" command in sed

    I *think* the way it works is that because you have not swapped anything into the hold buffer, it is empty (i.e. a blank line); so {g;p} puts a blank line into pattern space and then prints it

    So for example if you swap the pattern space into the hold space first, it will print the last line ($) instead of a blank line (also the matched line in this case - so you see it twice)

    Code:
    $ sed -nrs '/above/p;${h;g;p}' a1.txt
    there are two lines above this one
    there are two lines above this one
    or (to make it clearer)

    Code:
    $ echo "last line" >> a1.txt
    $
    $ sed -nrs '/above/p;${g;p}' a1.txt
    there are two lines above this one
    
    $ sed -nrs '/above/p;${h;g;p}' a1.txt
    there are two lines above this one
    last line

  3. #3
    Join Date
    Dec 2007
    Location
    Bombay
    Beans
    5,532
    Distro
    Lubuntu 14.04 Trusty Tahr

    Re: Help wanted to understand the "g" command in sed

    Thanks for your answer
    So h is the "opposite" of g? I'll play with that a bit and come back and mark the thread "solved" if I don't have any further questions.
    de gustibus et coloribus non est disputandum -- Wiktionary

  4. #4
    Join Date
    Feb 2013
    Beans
    Hidden!

    Re: Help wanted to understand the "g" command in sed

    Yes, steeldriver is absolutely right. In case you're trying to understand how that script works, I put ${g;p} in there just to force a blank line at the end of output from each file processed by sed. As the hold space contains nothing at that point, g simply erases the previous contents of the last line, but retains the newline at its end, and p prints the now empty line.
    Last edited by schragge; March 22nd, 2013 at 09:22 AM.

  5. #5
    Join Date
    Dec 2007
    Location
    Bombay
    Beans
    5,532
    Distro
    Lubuntu 14.04 Trusty Tahr

    Re: Help wanted to understand the "g" command in sed

    Quote Originally Posted by schragge View Post
    Yes, steeldriver is absolutely right. In case you're trying to understand how that script works, I put ${g;p} in there just to force a blank line at the end of output from each file handled by sed. As the hold space contains nothing at that point, g simply erases the previous contents of the last line, but retains the newline at its end, and p prints the now empty line.
    Thanks for clarifying but it wasn't that script but the first one you posted for me
    de gustibus et coloribus non est disputandum -- Wiktionary

  6. #6
    Join Date
    Feb 2013
    Beans
    Hidden!

    Re: Help wanted to understand the "g" command in sed

    Actually, I could do $s/.*//p to the same effect there. And with the GNU sed, it's also possible to write ${z;p}

  7. #7
    Join Date
    Dec 2007
    Location
    Bombay
    Beans
    5,532
    Distro
    Lubuntu 14.04 Trusty Tahr

    Re: Help wanted to understand the "g" command in sed

    Quote Originally Posted by schragge View Post
    Actually, I could do $s/.*//p to the same effect there. And with the GNU sed, it's also possible to write ${z;p}
    I took the code I referred to above and changed it slightly and then put in the other two options you provided:

    Code:
    [10:28 PM] ~ $ time sed -nrs '1d;/^(Name|Exec)=/p;${g;p}' /usr/share/applications/*.desktop > ab
    
    real	0m0.012s
    user	0m0.008s
    sys	0m0.004s
    [10:28 PM] ~ $ time sed -nrs '1d;/^(Name|Exec)=/p;$s/.*//p' /usr/share/applications/*.desktop > ac
    
    real	0m0.011s
    user	0m0.008s
    sys	0m0.004s
    [10:28 PM] ~ $ time sed -nrs '1d;/^(Name|Exec)=/p;${z;p}' /usr/share/applications/*.desktop > ad
    
    real	0m0.012s
    user	0m0.004s
    sys	0m0.004s
    [10:29 PM] ~ $
    I guess for a small set, the difference isn't significant but if the set is large, there would be a preference for the most efficient. So what do real, user, and sys mean here? I took a look at `man time` but ended up no wiser
    de gustibus et coloribus non est disputandum -- Wiktionary

  8. #8
    Join Date
    Feb 2013
    Beans
    Hidden!

    Re: Help wanted to understand the "g" command in sed

    At least, z should be more efficient than s/.*// as stated in the sed info page. I guess it should also be more efficient than g as all it does is discarding everything in the current pattern space. I cannot say how s/.*// and g would compare. However, z is a GNU extension. It's unportable and won't work with other sed impementations, e.g. with the BusyBox sed applet. This means you cannot use z in sed scripts invoked from initramfs rescue shell.
    Last edited by schragge; March 22nd, 2013 at 09:21 AM.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •