Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to understand, how following sed command is working:

sed -nre "/jar$/ { x; d; }; /class$/ { x; p; }

Actually it is part of another command to find a particular class file from the given list of jar files:

find . -name "*jar" -print -exec jar -tf '{}' \; | grep -E "jar$|CLASS_NAME" | sed -nre "/jar$/ { x; d; }; /class$/ { x; p; } "
share|improve this question
add comment

1 Answer

up vote 9 down vote accepted

First, let's start from commandline options:

  • -n disables normal output of the buffer. Only lines that are requested to print (e.g. with p command) will be printed

  • -r enables extended regexp

  • -e is not really needed when we are specifying sed commands in command line and not from file

Now comes sed commands. There are two, separated with ; character. Sed goes line by line and executes those two commands in order. But only if they match. Here, both commands are prefixed with /SOMETHING/ which means this command is only executed if current line matches SOMETHING regexp.

/jar$/ regexp only matches if current line ends with jar. Similar /class$/ regexp only matches if current line ends with class. Now if particular line matches, it executes two commands in it (they are grouped with {}) - in first case it is x and then d command. In second case it's x and then p command.

  • x command is eXchange. sed has a buffer that you can use to store some lines. This command exchanges this buffer with current line (so current line goes to this buffer and buffer content becomes current line).

  • d command discards current line, reads new one and starts executing sed commands from the first one (all the commands after d are ignored for current line).

  • p command prints current line. Since we use -n command arguments only lines printed with p will be shown at output.

So to sum up:

  • /jar$/ { x; d; } means - if current line ends with jar, save it in the buffer

  • /class$/ { x; p; } means - if current line ends with class, get buffer contents (which should contain last line ending with jar, unless there was a file ending with class already) and print it

share|improve this answer
1  
Just an extra point about d. It doesn't effect this case, but it can in others. From: Command Summary for sed: d "Delete line(s) from pattern space. Thus, the line is not passed to standard output. A new line of input is read and editing resumes with first command in script." ... +1 btw –  Peter.O Sep 17 '12 at 14:52
    
Yes, this is true. In other words d command not only removes the line from current buffer but since there is nothing in it, there's not much point in continuing with more commands. This is why it ignores the rest of them and starts from first command with the next line. –  Krzysztof Adamski Sep 17 '12 at 16:01
1  
There are always fringe cases... Sometime you may want to append some text (a), or some such thing, after a "delete".. for this, you may need to avoid d or perhaps use the D command Delete first part (up to embedded newline) of multiline pattern space created by N command and resume editing with first command in script. If this command empties the pattern space, then a new line of input is read, as if the d command had been executed. ... I just thought I'd make mention of the d as it has caught me out once or twice. –  Peter.O Sep 17 '12 at 16:37
    
Definitively. I can't provide all the detail about sed in this answer as I would have to rewrite the whole manual. I will add this as a note to this question since it indeed may be confusing in some cases. –  Krzysztof Adamski Sep 17 '12 at 16:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.