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 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
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. 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
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)
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". 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)
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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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;
|
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>
|
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>
|
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...
| |
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"
|
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...
|
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,...
|
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...
|
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,...
|
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();...
| |
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
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...
| |