473,668 Members | 2,486 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Problem with boost::regex_re place

I hope a Boost question is not too off-topic here. It seems that
upgrading to Boost 1.33 broke some old regex code that used to work. I
have reduced the problem to this simple example:

cout << boost::regex_re place(string("f oo"),
boost::regex(". *"),
string("bar")) << endl;

The above code prints "barbar" where I expect "bar". Can anyone shed
some light on this? It used to work with 1.30 (though regex_replace
was called regex_merge). It seems to me that ".*" should match all of
"foo" and replace it with "bar", so where does the second "bar" in
"barbar" come from?

Through trial and error I discovered that adding boost::match_no t_null
to the normal boost::match_de fault flag restores the desired behavior,
but I'm not sure if this is significant or just coincidence.

Derek

Oct 5 '05 #1
7 7792

de**********@gr og.net wrote:
I hope a Boost question is not too off-topic here. It seems that
upgrading to Boost 1.33 broke some old regex code that used to work. I
have reduced the problem to this simple example:

cout << boost::regex_re place(string("f oo"),
boost::regex(". *"),
string("bar")) << endl;

The above code prints "barbar" where I expect "bar". Can anyone shed
some light on this? It used to work with 1.30 (though regex_replace
was called regex_merge). It seems to me that ".*" should match all of
"foo" and replace it with "bar", so where does the second "bar" in
"barbar" come from?

Through trial and error I discovered that adding boost::match_no t_null
to the normal boost::match_de fault flag restores the desired behavior,
but I'm not sure if this is significant or just coincidence.

The ".*" expression matches zero or more characters. The "zero" means
it doesn't need any characters to make a match; so when there are zero
characters left to search, the patttern finds another match.

Because it matches no string at all, a .* search pattern is rarely the
best choice. It's more likely that the regex expression .+ is the
intended search string.

Greg

Oct 6 '05 #2
Greg wrote:
I hope a Boost question is not too off-topic here. It
seems that upgrading to Boost 1.33 broke some old regex
code that used to work. I have reduced the problem to
this simple example:

cout << boost::regex_re place(string("f oo"),
boost::regex(". *"),
string("bar")) << endl;

The above code prints "barbar" where I expect "bar".
Can anyone shed some light on this? It used to work
with 1.30 (though regex_replace was called regex_merge).
It seems to me that ".*" should match all of "foo" and
replace it with "bar", so where does the second "bar" in
"barbar" come from?

Through trial and error I discovered that adding
boost::match_no t_null to the normal boost::match_de fault
flag restores the desired behavior, but I'm not sure if
this is significant or just coincidence.


The ".*" expression matches zero or more characters. The
"zero" means it doesn't need any characters to make a
match; so when there are zero characters left to search,
the patttern finds another match.

Because it matches no string at all, a .* search pattern
is rarely the best choice. It's more likely that the regex
expression .+ is the intended search string.


Thanks, Greg. Your explanation is precisely why I thought adding the
boost::match_no t_null flag fixed the problem -- because it "specifies
that the expression can not be matched against an empty sequence."
Unfortunately that explanation seems contradicted by this example,
which is my original example with the empty sequence "" as input
instead of "foo":

cout << boost::regex_re place(string("" ), // empty sequence
boost::regex(". *"),
string("bar")) << endl;

By your reasoning the ".*" should match the empty input sequence "" and
the output should be "bar". However, the output I get is the empty
sequence "", not "bar".

I am also bothered that in other languages I routinely use -- and in
previous versions of Boost -- the expression ".*" does not match the
empty sequence. It all seems very inconsistent.

Oct 6 '05 #3
de**********@gr og.net wrote:
Greg wrote:
I hope a Boost question is not too off-topic here. It
seems that upgrading to Boost 1.33 broke some old regex
code that used to work. I have reduced the problem to
this simple example:

cout << boost::regex_re place(string("f oo"),
boost::regex(". *"),
string("bar")) << endl;

The above code prints "barbar" where I expect "bar".
Can anyone shed some light on this? It used to work
with 1.30 (though regex_replace was called regex_merge).
It seems to me that ".*" should match all of "foo" and
replace it with "bar", so where does the second "bar" in
"barbar" come from?

Through trial and error I discovered that adding
boost::match_no t_null to the normal boost::match_de fault
flag restores the desired behavior, but I'm not sure if
this is significant or just coincidence.


The ".*" expression matches zero or more characters. The
"zero" means it doesn't need any characters to make a
match; so when there are zero characters left to search,
the patttern finds another match.

Because it matches no string at all, a .* search pattern
is rarely the best choice. It's more likely that the regex
expression .+ is the intended search string.


Thanks, Greg. Your explanation is precisely why I thought adding the
boost::match_no t_null flag fixed the problem -- because it "specifies
that the expression can not be matched against an empty sequence."
Unfortunately that explanation seems contradicted by this example,
which is my original example with the empty sequence "" as input
instead of "foo":

cout << boost::regex_re place(string("" ), // empty sequence
boost::regex(". *"),
string("bar")) << endl;

By your reasoning the ".*" should match the empty input sequence "" and
the output should be "bar". However, the output I get is the empty
sequence "", not "bar".


I am not able to reproduce this behavior with the default boost
configuration. The above line of code does output "bar" with boost 1.33
on my machine. Note that there is an unspecified default argument which
should be boost::match_de fault. In other words, the above line should
be equivalent to this statement:

cout << boost::regex_re place(string("" ), // empty sequence
boost::regex(". *"),
string("bar"),
boost::match_de fault) << endl;

Replacing "boost::match_d efault" with "boost::match_n ot_null" or with
"boost:: match_not_dot_n ull" changes the output to a zero-length
string, as expected.

You may wish to run the boost::regex test suite that is part of the
distribution to ensure that your build was properly compiled.

Greg

Oct 6 '05 #4
Greg wrote:

The ".*" expression matches zero or more characters. The "zero" means
it doesn't need any characters to make a match; so when there are zero
characters left to search, the patttern finds another match.

Because it matches no string at all, a .* search pattern is rarely the
best choice. It's more likely that the regex expression .+ is the
intended search string.


However, under the maximum munch rule, in an otherwise unconstrained
search like the one at issue it should match the entire target sequence.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Oct 6 '05 #5
Greg wrote:
I am not able to reproduce this behavior with the default boost
configuration. The above line of code does output "bar" with boost 1.33
on my machine. Note that there is an unspecified default argument which
should be boost::match_de fault. In other words, the above line should
be equivalent to this statement:

cout << boost::regex_re place(string("" ), // empty sequence
boost::regex(". *"),
string("bar"),
boost::match_de fault) << endl;

Replacing "boost::match_d efault" with "boost::match_n ot_null" or with
"boost:: match_not_dot_n ull" changes the output to a zero-length
string, as expected.

You may wish to run the boost::regex test suite that is part of the
distribution to ensure that your build was properly compiled.

Greg


You are quite right; I'm not sure why it didn't work before, but I
re-compiled my example and sure enough ".*" does indeed match the empty
string. That is, the folowing code outputs "bar":

cout << regex_replace(s tring(""), // empty sequence
regex(".*"),
string("bar"),
match_default) << endl;

However, going back to the original example, I'm still confused about
one thing. Recall that the following code outputs "barbar":

cout << regex_replace(s tring("foo"),
regex(".*"),
string("bar"),
match_default) << endl;

So if I understand everything you've said, ".*" matches "foo" and
replaces it with "bar", and then it matches the remaining empty
sequence and outputs "bar" again (hence "barbar"). However, as Mr.
Becker points out, the "maximum munch" rule suggests that the ".*"
should consume "foo" *and* the empty sequence that implicitly follows,
right? It seems to me that the "maximum munch" rule suggests the
output should be "bar", not "barbar".

Oct 6 '05 #6
de**********@gr og.net wrote:

So if I understand everything you've said, ".*" matches "foo" and
replaces it with "bar", and then it matches the remaining empty
sequence and outputs "bar" again (hence "barbar"). However, as Mr.
Becker points out, the "maximum munch" rule suggests that the ".*"
should consume "foo" *and* the empty sequence that implicitly follows,
right? It seems to me that the "maximum munch" rule suggests the
output should be "bar", not "barbar".


No, the maximum munch rule consumes the three characters, leaving an
empty target string. The next attempt to match ".*" succeeds, so there
is a second match. Having just matched an empty string, the search
algorithm now requires a non-null match, which fails, and the search
terminates. So you should get "barbar", because you got two matches. At
least, that's what I currently think, but I'm at the C++ Standards
Committee meeting, and half listening to a discussion of concept
checking, so I don't promise that I've analyzed it correctly. However,
our implementation hit an infinite loop on your example because it
didn't force non-null for the search after an empty match, and once I
fixed that, I got the same result as you're seeing. <g>

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Oct 6 '05 #7
Pete Becker wrote:
So if I understand everything you've said, ".*" matches "foo" and
replaces it with "bar", and then it matches the remaining empty
sequence and outputs "bar" again (hence "barbar"). However, as Mr.
Becker points out, the "maximum munch" rule suggests that the ".*"
should consume "foo" *and* the empty sequence that implicitly follows,
right? It seems to me that the "maximum munch" rule suggests the
output should be "bar", not "barbar".


No, the maximum munch rule consumes the three characters, leaving an
empty target string. The next attempt to match ".*" succeeds, so there
is a second match. Having just matched an empty string, the search
algorithm now requires a non-null match, which fails, and the search
terminates. So you should get "barbar", because you got two matches. At
least, that's what I currently think, but I'm at the C++ Standards
Committee meeting, and half listening to a discussion of concept
checking, so I don't promise that I've analyzed it correctly. However,
our implementation hit an infinite loop on your example because it
didn't force non-null for the search after an empty match, and once I
fixed that, I got the same result as you're seeing.


Thanks for the explanation -- to you and Greg both. My world makes a
little more sense now.

Oct 6 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
3822
by: Andrew Maclean | last post by:
I guess this problem can be distilled down to: How do I search through a string, find the first matching substring, replace it, and continue through the string doing this. Can replace_if() be used to do this? Here is a concrete example: If I have a string with sequences of CRLF and possibly just CR's, is there a simple way of replacing the CRLF characters with a LF? If you look at the function below is it possible to use a replace_if...
7
4831
by: Aek | last post by:
Hi everyone, I am trying to construct a regular expression and format string to use with a boost::regex_replace() In my file the sample text is: // .fx shader file FLOAT JOE 3545f; FLOAT BLOGS -3343f; FLOAT AMBIENT 2300.0f;
3
2640
by: Yahooooooooo | last post by:
Hi, whats the issue in below code ... #include <iostream> #include <fstream> #include <sstream> #include <string> #include <iterator> #include <boost/regex.hpp>
1
4449
by: Yahooooooooo | last post by:
Just practicing BOOST regular expressions....giving errors... -- wanted to replace SPACE with NULL. #include <iostream> #include <fstream> #include <sstream> #include <string> #include <iterator> #include <boost/regex.hpp>
8
2526
by: Marcus Kwok | last post by:
Is std::string::npos portably able to be incremented? For example, I want to insert some text into a string. If a certain character is found, I want to insert this text immediately after this character; otherwise I insert at the beginning of the string. On my implementation string::npos has the value of (string::size_type)-1, so incrementing it will make it 0, but can I rely on it? Also, say that the character occurs at the end of...
8
1464
by: g.vukoman | last post by:
Hi all, I asking me how to design my method. Should I use pointer only? Or references? Or Values? I don't know... Below is a small method to read the mem amount of a machine. Fell free to edit the src below #include "MemSysInfo.h"
3
4533
by: rottmanj | last post by:
In my application I get a string from my datasource that I need to replace some of the bad chars in the strings. Right now I have written a pretty standard regex that should replace any of the bad chars in the strings. However, instead of removing the bad chars it removes all chars from the string. The bad chars I am trying to replace are /'() Here is the current code that I am testing with. boost::regex const...
0
8381
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8893
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8586
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
5681
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4205
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4380
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2792
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2026
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1786
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.