10

I wanted to do a range limited search in sed so I tried

sed -n '195,210 /add/ p' <file>

Which gave

sed: -e expression #1, char 9: unknown command: `/'

Purely as a guess, I tried adding curly braces:

sed -n '195,210{/add/p}' <file>

And it was successful, but Im trying to understand why it worked with the braces were added.
I kind of get, that in bash, braces can delimit an expression (and possibly increase its order of execution), but in the case of sed what are these braces doing?

Relevant info

$ sed --version
sed (GNU sed) 4.2.2

$ bash --version
GNU bash, version 4.3.11

3 Answers 3

14

Per the POSIX standard's page on sed:

The script shall consist of editing commands of the following form:

[address[,address]]function

where function represents a single-character command verb from the list in Editing Commands in sed, followed by any applicable arguments.

So the first non-blank character after the address is taken as a command verb - in your particular case it's / hence the error: char 9: unknown command: '/'.
The braces are referenced further down:

[2addr] {editing command
editing command
...
}
    Execute a list of `sed` editing commands only when the pattern space is selected.  …

[2addr] is an indicator that the maximum number of permissible addresses is two.

To clarify a point made above, the Addresses section of sed(1) says:

Sed commands can be given with no addresses, in which case the command will be executed for all input lines; with one address, in which case the command will be executed only for input lines which match that address; or with two addresses, in which case the command will be executed for all input lines which match the inclusive range of lines starting from the first address and continuing to the second address.  Three things to note about address ranges: the syntax is addr1,addr2 (i.e., the addresses are separated by a comma);
        … (and other stuff not relevant to this discussion)

The gnu info page (info sed) has a similar description of { and }, under "3.4 Often-Used Commands":

{ COMMANDS }
    A group of commands may be enclosed between { and } characters. This is particularly useful when you want a group of commands to be triggered by a single address (or address-range) match.

Otherwise said, braces are used to apply multiple commands at the same address or to nest addresses.
The standard isn't very explicit here1 but the left brace { is actually a command that starts a group of other sed commands (the group ends with a right brace }).

And, at the risk of really going TL;DR, the issue is that 195, 210, and /add/ are all addresses.  No sed commands can be invoked with three addresses.  So the way to make your command work is to invoke the { command on the address range 195,210, and then (within that range) invoke the p command on the address /add/.


1:
though if you read the entire page it is mentioned that:
Command verbs other than {, a, b, c, i, r, t, w, :, and # can be followed by...

7
  • excellent, thanks. This was the only answer that addressed the fact that other "groups of multiple commands" dont require braces e.g. sed -n '195,210s/old/new/p' <file> works fine. Links to POSIX standard also useful. Jun 1, 2015 at 22:31
  • 1
    @user4668401 - note that 195,210s/old/new/p is actually a range followed by a single command: s; in this case p is not a command, it is a flag (it means print if a replacement was made) see the manual for s syntax: s/regexp/replacement/flags. That's why it works without braces... Jun 1, 2015 at 22:49
  • ah right. So in the case of this command: sed -n '195,210{/add/p}' <file>, there are 2 commands, 1. the /add/ regex match and 2. the p, print command and that is why the {...} brace block is needed? Jun 1, 2015 at 23:21
  • @user4668401 - yes, there are two commands but the first one isn't your /add, it's actually { and that allows you to nest an address inside another one. Answer edited. Jun 1, 2015 at 23:45
  • I want to mention that multiple addresses are possible in vi (or ex), and they look quite similar to sed addresses.
    – Wildcard
    Mar 4, 2016 at 9:47
3

According to the documentation for sed the curly braces are used to group commands together. So

sed -n '195,210{/add/p}' <file>

Is first treated as an address range 195,210 with a block command. The block command then consists of the address specification /add/ with the command print p

0

The sed syntax goes like

address/command.

So 195,210 is the first address you match, but then you want to execute a new command within that range, namely match "add", then print. Therefore you need to group this extra command using the curly braces.

You must log in to answer this question.

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