I need to manipulate text that's in a file. I need to append a right parenthesis – ) – after every number that's preceded by a comma – , – e.g.,

  • ,4   ➜ ,4)
  • ,15,15)

I am struggling to find the proper way to do this with sed. I tried the following, which works for 1 digit but can't seem to be extended to 2 digits (so it's fine for first line above but not the second):

sudo sed 's/,\([0-9]\)/,\1)/g' filename

So then I tried the following for 2 digits:

sudo sed 's/,\([0-9]([0-9]?\)/,\1)/g' filename

This didn't do anything - the file remained unchanged, though I did not receive an error message. What is the proper way to search for one required digit and a second optional digit and then move them both into the replacement text? I still need to accomplish this:

  • ,15,15)

Any advice would be greatly appreciated.

  • Certainly the answer with \{,2\} is more syntaxically correct but you variant is workable too if your escape "question mark" \? and remove extra-bracket ( between ][ : sed 's/,[0-9][0-9]\?/&)/g' filename – Costas Mar 6 '15 at 18:57
  • sed 's/,[0-9]\{1,2\}/&)/g'. @Costas, \? is GNU specific. The portable/standard equivalent is \{0,1\}. – Stéphane Chazelas Mar 7 '15 at 11:20
  • @StéphaneChazelas Sure, but if we told re BRE: Basic vs Extended Regular Expressions In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \). – Costas Mar 7 '15 at 12:33
  • 1
    @Costas, in GNU BRE only. In standard BRE, there's no \? nor \+. – Stéphane Chazelas Mar 7 '15 at 14:44

You were almost there, try this:

sudo sed 's/,\([0-9]\{1,2\}\)/,\1\)/g' filename

Here in addition to your command i have just added \{1,2\} which matches the previous regex between one to two times i.e. from a minimum of one time to a maximum of two times.

\([0-9]\{1,2\}\) explained:

  • [0-9] will match a single digit between 0 to 9
  • {1,2} will match the previous regex from one to a maximum of two times. So, one match is a must and the second is optional (as you want)
  • () will make a regex group so that we can reference it later.
  • Also note that we have used '\' in front of all extended regex syntax so that they they don't get treated literally. We could have used the -r switch (extended regex) with gnu sed, in that case we could just write:

    sudo sed -r 's/,([0-9]{1,2})/,\1\)/g' filename

EDIT: If you want to match any number of digits (minimum one) after comma you can do:

sudo sed 's/,\([0-9]\{1,\}\)/,\1\)/g' filename

or more simply:

sudo sed 's/,\([0-9]\+\)/,\1\)/g' filename
  • Thanks for your input, but the command you supplied doesn't seem to work: ~/html$ sudo sed 's/,([0-9]{,2})/,\1/g' calendar3.php sed: -e expression #1, char 20: invalid reference \1 on `s' command's RHS – Beeb Mar 6 '15 at 18:31
  • @Beeb: Aren't you using gnu sed? – heemayl Mar 6 '15 at 18:34
  • @Beeb: Got it..please check my answer now.. – heemayl Mar 6 '15 at 18:36
  • Thank you for modifying your answer. This worked perfectly. Can you explain it a bit more? In particular I am wondering about these parentheses --->([0-9]\{,2\})<--- and also the backslashes. Are they actually just a unit together ( and )? If so, what do they do? Thanks again. – Beeb Mar 6 '15 at 18:44
  • 1
    @mikeserv: Edited and added.. – heemayl Mar 7 '15 at 10:52

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.