1

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.

4
  • 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, 2015 at 18:57
  • sed 's/,[0-9]\{1,2\}/&)/g'. @Costas, \? is GNU specific. The portable/standard equivalent is \{0,1\}. Mar 7, 2015 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, 2015 at 12:33
  • 1
    @Costas, in GNU BRE only. In standard BRE, there's no \? nor \+. Mar 7, 2015 at 14:44

1 Answer 1

1

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
7
  • 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, 2015 at 18:31
  • @Beeb: Aren't you using gnu sed?
    – heemayl
    Mar 6, 2015 at 18:34
  • @Beeb: Got it..please check my answer now..
    – heemayl
    Mar 6, 2015 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, 2015 at 18:44
  • 1
    @mikeserv: Edited and added..
    – heemayl
    Mar 7, 2015 at 10:52

You must log in to answer this question.

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