0

I am trying with the following sed command:

sed 's/shared:core:([0-9]{1,4}(\.[0-9a-z]{1,6}){1,5})/shared:core:1.1.1/' test.txt

to replace the content of test.txt

shared:core:0.0.2

I expect it to become

shared:core:1.1.1

But nothing is happening. I think I need a little hint on how that works with sed

6
  • Please edit your question and explain what you are trying to capture with that regular expression. It looks like you want to find 1 to 5 repetitions of "1-4 numbers followed by one to six repetitions of a . followed by one to 6 alphanumeric characters". But this doesn't make much sense with the input example you have given.
    – terdon
    Dec 22, 2021 at 11:20
  • @terdon he is using parens for grouping, not capture. He wants to normalize a version number, presumably for later operation on the file (like diffing it with a reference version).
    – David G.
    Dec 22, 2021 at 11:25
  • @DavidG. yes, I know. That's what I describe.
    – terdon
    Dec 22, 2021 at 11:28
  • @terdon I simply want to replace 0.0.2 with 1.1.1 as described in the question
    – xetra11
    Dec 22, 2021 at 13:02
  • So all you need is sed 's/0\.0\.2/1.1.1/? If so, why do you have such a complicated regex? Are there any more lines in the file that you need to avoid?
    – terdon
    Dec 22, 2021 at 13:03

2 Answers 2

1

You are using (foo) which is mean to capture the string foo. However, by default, sed will read that as a literal ( followed by foo and another ) and since you don't have any ( or ) in your input, that will never match.

For sed to use capturing parentheses, you need t escape them (\(foo\)) or you need to use -E. You don't actually need this at all here though because you are never referring to the thing you were trying to capture. All you need is:

$ sed 's/shared:core:.*/shared:core:1.1.1/' file 
shared:core:1.1.1

Or even:

$ sed -E 's/(shared:core:).*/\1:1.1.1/' file 
shared:core::1.1.1

Or even simpler:


$ sed -E 's/(.*):.*/\1:1.1.1/' file 
shared:core:1.1.1

Now, if your input is more complicated and what you are trying to match is 1 to 5 repetitions of 1-4 numbers followed by one to six repetitions of a . followed by one to 6 alphanumeric characters (which is what the regex you used does), you can use your version, just add -E (assuming your sed implementation supports it):

$ sed -E 's/shared:core:([0-9]{1,4}(\.[0-9a-z]{1,6}){1,5})/shared:core:1.1.1/' file 
shared:core:1.1.1

Or, if you can't use -E:

$ sed  's/shared:core:\([0-9]\{1,4\}\(\.[0-9a-z]\{1,6\}\)\{1,5\}\)/shared:core:1.1.1/' file 
shared:core:1.1.1

Although I fear this might not be 100% portable, not sure.

Finally, remember that sed doesn't change the input file unless you give it the -i option. So if you are expecting the original file to change, use sed -i .... file.

1

By default, sed uses basic regular expressions. Add the -E option for extended regular expressions. Thus:

sed -E 's/shared:core:([0-9]{1,4}(\.[0-9a-z]{1,6}){1,5})/shared:core:1.1.1/' test.txt

Alternatively, convert to a basic regular expression. Thus:

sed 's/shared:core:\([0-9]\{1,4\}\(\.[0-9a-z]\{1,6\}\)\{1,5\}\)/shared:core:1.1.1/' test.txt

Additionally, if you actually want the contents of the file to change, then you need to add the -i option, to cause an "in place" change. Thus:

sed -E 's/shared:core:([0-9]{1,4}(\.[0-9a-z]{1,6}){1,5})/shared:core:1.1.1/' -i test.txt
6
  • using -E did not change the test.txt version either
    – xetra11
    Dec 22, 2021 at 11:15
  • @xetra11 Are you expecting the file to change?
    – David G.
    Dec 22, 2021 at 11:18
  • yes I do. I thought that is what sed does?
    – xetra11
    Dec 22, 2021 at 13:02
  • 1
    @xetra11 For the GNU version of sed (and probably most others), sed -i-E ... will save the old file like test.txt-E, and will not use the extended regular expressions. What you want is sed -i -E ... Notice the space between -i and -E.
    – David G.
    Dec 23, 2021 at 5:27
  • 1
    @xetra11 No, sed doesn't normally change its input. sed normally reads from something that could be a file but is quite often a pipe, modifies it, and writes it to standard output, which is often also a pipe. "sed" actually is from "Stream EDitor". The -i option is a more recent addition that allows a file to be changed "inplace". (-E is also more recent.)
    – David G.
    Dec 23, 2021 at 5:33

You must log in to answer this question.

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