I have a file in the following format:

$ cat myfile     
12 42956    Cinema - 3D/Multiplex    
7  12560    Status Update    
5  184   Movie  

I am trying to add double quotes to the text description.
I can't understand why the following regex doesn't work:
$ sed -E 's/\b[0-9]+\b\s*\b[0-9]+\b\s*([^\s]+)/"\1"/g' myfile

My question is about specifically this regex and not another approach to do the same thing. I


As far as I know, \s is a Perl regular expression which is the same as [[:blank:]] in sed. Inside [ ... ], \s means "an \ and an s". Notice too that even if [^\s]+ would have been the same as [^␣]+, that would have failed to match Status Update due to the space in the middle.

The replacement will replace all of the match with the first group in double quotes. You probably want to catch all three columns or you'll end up with only the last column. And as you're trying to match the whole line, you should anchor the expression in the beginning and end with ^ and $, and drop the g flag at the end.


$ sed -E 's/[[:alpha:]].+/"&"/' myfile
12 42956    "Cinema - 3D/Multiplex    "
7  12560    "Status Update    "
5  184   "Movie  "

This will find the last column by the fact that its data seems to always start with a non-digit. The expression will simply match the rest of the line from the first alphabetic character and replace all of the match with a double-quoted version of the match.

The data in the question had spaces at the end, and the the quotes will include these. To avoid the spaces at the end:

$ sed -E -e 's/[[:blank:]]*$//' -e 's/[[:alpha:]].+/"&"/' myfile
12 42956    "Cinema - 3D/Multiplex"
7  12560    "Status Update"
5  184   "Movie"


while read -r a b c; do printf '%d\t%d\t"%s"\n' "$a" "$b" "$c"; done <myfile
12      42956   "Cinema - 3D/Multiplex"
7       12560   "Status Update"
5       184     "Movie"
| improve this answer | |
sed -E 's/\b([0-9]+\b\s*\b[0-9]+)\b\s*([^\s]+)/\1 "\2"/g' myfile

This only adds double quotes around your text.

Saving the digits and spaces in a group \1 and the string in another group (\2), sed outputs group 1 (\1) followed by a space followed by a double quote followed by the second group (\2) followed by the final double quote.

You could shorten this up a bit by grouping all digits and spaces in one group ([0-9, ]*)and anything after digits in another group (.+).

This gives:

sed -E 's/([0-9, ]*)(.+)/\1 "\2"/g' myfile
12 42956     "Cinema - 3D/Multiplex"
7  12560     "Status Update"
5  184    "Movie"
| improve this answer | |
  • I am not clear how ([0-9, ]*) captures 12 42956 – Jim Feb 9 '17 at 23:18
  • The ()'s capture a match defined as a character class by square brackets [ ] any digit, 0-9, or space. the "*" grabs as many of those characters as possible. As it is the first defined group in the left hand side of 's///' the match can be referenced in the right hand side by \1. – John Mehorter Feb 9 '17 at 23:38

Because Mac OSX sed does not support \s. Only GNU sed supports \s.

On Mac OSX, \s does not work, even with $'' ANSI-C quoting.

$ echo $'1\t2 3' | sed 's/\s//g'
1   2 3
$ echo $'1\t2 3' | sed $'s/\s//g'
1   2 3

Instead, you can use [[:space:]]

$ echo $'1\t2 3' | sed 's/[[:space:]]//g'

Or you can use [ \t], but you'll need the $'' ANSI-C quoting for the tab character.

$ echo $'1\t2 3' | sed $'s/[ \t]//g'
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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