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 Commented Mar 6, 2015 at 18:57
  • sed 's/,[0-9]\{1,2\}/&)/g'. @Costas, \? is GNU specific. The portable/standard equivalent is \{0,1\}. Commented 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 \). Commented Mar 7, 2015 at 12:33
  • 1
    @Costas, in GNU BRE only. In standard BRE, there's no \? nor \+. Commented 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 Commented Mar 6, 2015 at 18:31
  • @Beeb: Aren't you using gnu sed? Commented Mar 6, 2015 at 18:34
  • @Beeb: Got it..please check my answer now.. Commented 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. Commented Mar 6, 2015 at 18:44
  • 1
    @mikeserv: Edited and added.. Commented Mar 7, 2015 at 10:52

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.