4

I'm going crazy trying to follow the sed BRE (Basic Regular Expression) rules to replace a pretty simple occurrence in an HTML file.

I think I'm following the spec correctly, but none of my attempts are working.

What I'd like to do is replace the contents of one meta tag with something new (which I'm calculating as part of the script I'm writing). Basically, the meta tag looks like this:

<meta version="v0.103.2" />

It always contains an attribute which follows that syntax, which in a JS regular expression could be characterized as:

/version=\"v[0-9]+\.[0-9]+\.[0-9]+\"/g

So I've tried a whole bunch of sed commands to get this working, and it just doesn't seem to work as documented, unless I'm misunderstanding things. Some of the commands I've tried:

I'm on a Mac (which matters because of sed syntax changes between Unix/Linux), and this accounts for the '' in the commands below.

✗ sed -i -E '' s/version=\"v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/version=\"whatever/g ./src/index.html
✗ sed -i -E '' s/version=\"v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/version=\"whatever/g './src/index.html'
✗ sed -i -E s/version=\"v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/version=\"whatever/g ./src/index.html
✗ sed -i -E s/version=\"v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/version=\whatever/g ./src/index.html
✗ sed -i -E s/version=\"v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/version=\"whatever/g ./src/index.html
✗ sed -i '' s/version=\"v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/version=\"whatever/g ./src/index.html 
✗ sed -i '' s/version=\"v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/version=\whatever/g ./src/index.html 
✗ sed -i '' s/version=\"v[:digit:]+\.[:digit:]+\.[:digit:]+/version=\whatever/g ./src/index.html 
✗ sed -i '' s/v[:digit:]+\.[:digit:]+\.[:digit:]+/whatever/g ./src/index.html 
✗ sed -i '' s/v[:digit:]+[:punct:][:digit:]+[:punct:][:digit:]+/whatever/g ./src/index.html
✗ sed -i '' s/v[:digit:][:punct:][:digit:][:digit:][:digit:][:punct:][:digit:]+/whatever/g ./src/index.html 
✗ sed -i '' s/v[:digit:][:punct:][:digit:][:digit:][:digit:][:punct:][:digit:]/whatever/g ./src/index.html
✗ sed -i '' s/v[0-9]+\.[0-9]+.[0-9]+/whatever/g ./src/index.html
✗ sed -i '' s/version=\"[^ \"]+\"/whatever/g ./src/index.html
✗ sed -i '' s/version="[^ "]+"/whatever/g ./src/index.html 
✗ sed -i '' s/version=\"[^\"]+\"/whatever/g ./src/index.html 
✗ sed -i '' s/version=/whatever=/g ./src/index.html
✗ sed -i '' s/version=\"/whatever=\'/g ./src/index.html
✗ sed -i '' s/version=\"[^\"]/whatever=\"/g ./src/index.html

Help? It is finding the file correctly. When I try versions of this that don't include a regex (see third from the bottom), it replaces correctly, but somehow my regex syntax seems not to be working here.

Or can anyone think of an easier/more reliable way to do this?

Sasha
  • 6,224
  • 10
  • 55
  • 102

1 Answers1

2

You need to quote the regex and instead of + (that is treated as a literal + by the BRE POSIX) use either * (that matches 0 or more occurrences) or \{1,\} range quantifier (in BRE POSIX, the {n,m} must be written as \{m,n\}) that matches 1 or more occurrences.

Thus, you may use

sed -i '' "s/version=\"v[0-9]*\.[0-9]*\.[0-9]*\"/whatever=/g" ./src/index.html

With single quotes:

sed -i '' 's/version="v[0-9]*\.[0-9]*\.[0-9]*"/whatever=/g' ./src/index.html
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 2
    Why quote with double quotes and escape double quotes? Can just use single quotes, no need to escape double quotes? – Benjamin W. Jun 29 '17 at 16:33
  • @BenjaminW.: Yes, we can, you are not the first who tells me that, and not the first, or even the second time. I am mostly programming in C#, and am very accustomed to C# string literals that cannot be defined using single quotes. I have started to work with Linux,`grep`, `sed`, etc. quite recently. – Wiktor Stribiżew Jun 29 '17 at 16:39