5

I want to search-replace something containing whitespace on a bash command line, and I assumed sed would be the easiest way to go.

Using [ \t] denoting either tab or space, to match the whitespace, works as intended:

echo "abc xyz" | sed "s/[ \t]xyz/123/"
abc123

But using \s instead of [ \t] does not, to my surprise:

echo "abc xyz" | sed "s/\sxyz/123/"
abc xyz

I'm fairly new to bash so I might be missing something trivial, but no matter what I do, I can't get this to work. Using \\s instead of \s, using single quotes (' instead of "), putting the whitespace marker inside square brackets (like [\s] or even [\\s]), nothing seems to help..?

(edit) in case it differs from one sed / bash version to another: I'm working on OS X here.

Additionally, I noticed that when I add a + after the [ \t] whitespace part, to optionally grab multiple space/tab characters if present, it doesn't work anymore either...??

echo "abc xyz" | sed "s/[ \t]+xyz/123/"
abc xyz

(and again, also tried with \+ instead of +, and single quotes instead of double quotes, nothing helps)

fedorqui
  • 275,237
  • 103
  • 548
  • 598
RocketNuts
  • 9,958
  • 11
  • 47
  • 88
  • 3
    Interesting and related: [How to match whitespace in sed?](http://superuser.com/a/112837/204979). Basically, _For POSIX compliance, use the character class [[:space:]] instead of \s, since the latter is a GNU sed extension_ So you are probably working in a non-GNU `sed`. Could you provide the output of `sed --version`? – fedorqui May 04 '15 at 11:21
  • on sed here, it works as expected; as @fedorqui suggest, it is gnu sed indeed – guido May 04 '15 at 11:22
  • have you thoroughly read the sed man page on your system? It should document what does and does not work. Type `man sed` at a command prompt. – Bryan Oakley May 04 '15 at 11:25
  • Ah, thanks, `sed --version` says `illegal option -- -` so I guess it's not GNU :) – RocketNuts May 04 '15 at 11:27

2 Answers2

8

As seen in SuperUser's How to match whitespace in sed?:

For POSIX compliance, use the character class [[:space:]] instead of \s, since the latter is a GNU sed extension

So you are probably running a non-GNU sed version, hence \s not working to you.

You have two solutions:

  • To use (space) and \t together, like you were doing.
  • To use [[:space:]].
Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Confirmed, thanks, it works with [[:space:]] However, the + modifer still doesn't work, any ideas? Note that `[[:space:]]\{1,999\}` *does* work, but `[[:space:]]+` or `[[:space:]]\+` do not. – RocketNuts May 04 '15 at 11:28
  • 1
    To use `+` normally you need either to escape it: `\+` or to use `-r` for extended regex: `sed -r "s/[[:space:]]+/X/"` – fedorqui May 04 '15 at 11:31
  • 2
    @RocketNuts the [POSIX-compliant syntax](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_06) for _one or more matches_ Is `\{1,\}` - anything else is an extension. – Tom Fenech May 04 '15 at 11:36
1
echo 'abc xyz<>abcxyz' | sed 's/[[:space:]]xyz/123/g'
abc123<>abcxyz
echo 'abc xyz<>abcxyz' | sed "s/[[:space:]]xyz/123/g"
abc123<>abcxyz

doesn't work on very old sed version but fine on GNU sed as posix complaint (AIX, ...)

NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43