Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #38085 > unrolled thread

regex replaceAll?

Started byEric Douglas <e.d.programmer@gmail.com>
First post2018-03-01 06:19 -0800
Last post2018-03-02 02:25 +0100
Articles 20 on this page of 29 — 5 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-01 06:19 -0800
    Re: regex replaceAll? Andreas Leitgeb <avl@logic.at> - 2018-03-01 19:03 +0000
      Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-01 12:15 -0800
        Re: regex replaceAll? Daniele Futtorovic <da.futt.news@laposte.net> - 2018-03-01 21:51 +0100
          Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-01 13:36 -0800
            Re: regex replaceAll? Arne Vajhøj <arne@vajhoej.dk> - 2018-03-01 16:59 -0500
        Re: regex replaceAll? Andreas Leitgeb <avl@logic.at> - 2018-03-01 21:55 +0000
          Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-01 14:00 -0800
            Re: regex replaceAll? Andreas Leitgeb <avl@logic.at> - 2018-03-01 22:31 +0000
              Re: regex replaceAll? Arne Vajhøj <arne@vajhoej.dk> - 2018-03-01 17:52 -0500
                Re: regex replaceAll? Andreas Leitgeb <avl@logic.at> - 2018-03-02 00:14 +0000
              Re: regex replaceAll? Kiwi User <martin@mydomain.invalid> - 2018-03-02 00:43 +0000
                Re: regex replaceAll? Arne Vajhøj <arne@vajhoej.dk> - 2018-03-01 19:49 -0500
                  Re: regex replaceAll? Kiwi User <martin@mydomain.invalid> - 2018-03-02 01:33 +0000
                    Re: regex replaceAll? Arne Vajhøj <arne@vajhoej.dk> - 2018-03-02 13:00 -0500
                      Re: regex replaceAll? Kiwi User <martin@mydomain.invalid> - 2018-03-03 20:07 +0000
              Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-02 05:40 -0800
                Re: regex replaceAll? Andreas Leitgeb <avl@logic.at> - 2018-03-02 17:46 +0000
                  Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-02 10:38 -0800
                    Re: regex replaceAll? Andreas Leitgeb <avl@logic.at> - 2018-03-02 20:15 +0000
                      Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-02 12:43 -0800
                      Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-02 12:58 -0800
                        Re: regex replaceAll? Daniele Futtorovic <da.futt.news@laposte.net> - 2018-03-03 00:06 +0100
    Re: regex replaceAll? Daniele Futtorovic <da.futt.news@laposte.net> - 2018-03-01 20:29 +0100
      Re: regex replaceAll? Daniele Futtorovic <da.futt.news@laposte.net> - 2018-03-01 20:30 +0100
      Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-01 12:28 -0800
        Re: regex replaceAll? Daniele Futtorovic <da.futt.news@laposte.net> - 2018-03-01 21:40 +0100
      Re: regex replaceAll? Eric Douglas <e.d.programmer@gmail.com> - 2018-03-01 13:52 -0800
        Re: regex replaceAll? Daniele Futtorovic <da.futt.news@laposte.net> - 2018-03-02 02:25 +0100

Page 1 of 2  [1] 2  Next page →


#38085 — regex replaceAll?

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-03-01 06:19 -0800
Subjectregex replaceAll?
Message-ID<4a800440-39fe-4684-8369-e6a4e6b9d79f@googlegroups.com>
I hate to ask because I feel like I'm close and missing something stupid, but how do you do this?

String in = "abc aa bb cc a bb ccc   a b c abc aa bbb cc babacaca";

I've found we can replace every third space using this:
String out;
 out = in.replaceAll("(?<=\\G\\S*\\s\\S*\\s\\S*)\\s", "_");
System.out.println(out);

Result:
"abc aa bb_cc a bb_ccc  _a b c_abc aa bbb_cc babacaca"

Now I'm trying to replace the nth occurrence of a string.
The best I can find matches the nth sequential.

int n = 2;
String repl = "b";
 out = in.replaceAll("([.]*["+repl+"]{"+(n-1)+"}[.]*)"+repl,"$1_");
System.out.println(out);

Result:
"abc aa b_ cc a b_ ccc   a b c abc aa b_b cc babacaca"

What I'm looking for:
"abc aa _b cc a _b ccc   a _ c abc aa _b_ cc ba_acaca"

[toc] | [next] | [standalone]


#38087

FromAndreas Leitgeb <avl@logic.at>
Date2018-03-01 19:03 +0000
Message-ID<slrnp9gjk6.5mg.avl@logic.at>
In reply to#38085
Eric Douglas <e.d.programmer@gmail.com> wrote:
> I hate to ask because I feel like I'm close and missing something stupid, but how do you do this?
> String in = "abc aa bb cc a bb ccc   a b c abc aa bbb cc babacaca";
> I've found we can replace every third space using this:
> String out;
>  out = in.replaceAll("(?<=\\G\\S*\\s\\S*\\s\\S*)\\s", "_");
> System.out.println(out);
> Result:
> "abc aa bb_cc a bb_ccc  _a b c_abc aa bbb_cc babacaca"
>
> Now I'm trying to replace the nth occurrence of a string.
> The best I can find matches the nth sequential.
>
> int n = 2;
> String repl = "b";
>  out = in.replaceAll("([.]*["+repl+"]{"+(n-1)+"}[.]*)"+repl,"$1_");

[.] only matches a literal dot. That might be the root-cause of why it's
not working the way you like.

> System.out.println(out);
>
> Result:
> "abc aa b_ cc a b_ ccc   a b c abc aa b_b cc babacaca"
>
> What I'm looking for:
> "abc aa _b cc a _b ccc   a _ c abc aa _b_ cc ba_acaca"

[toc] | [prev] | [next] | [standalone]


#38090

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-03-01 12:15 -0800
Message-ID<44c665e1-e965-4e9b-8aa0-72aa20607e63@googlegroups.com>
In reply to#38087
On Thursday, March 1, 2018 at 2:03:47 PM UTC-5, Andreas Leitgeb wrote:
> 
> [.] only matches a literal dot. That might be the root-cause of why it's
> not working the way you like.
> 
> > System.out.println(out);
> >
> > Result:
> > "abc aa b_ cc a b_ ccc   a b c abc aa b_b cc babacaca"
> >
> > What I'm looking for:
> > "abc aa _b cc a _b ccc   a _ c abc aa _b_ cc ba_acaca"

The Pattern says the dot matches anything, but I tried many many variations.  Somehow the first pattern I mentioned which seems to be working for every 3rd occurrence of a blank space has a ?<= and a \\G in it, but any time I put those in the second pattern it didn't seem to do anything.

https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

[toc] | [prev] | [next] | [standalone]


#38093

FromDaniele Futtorovic <da.futt.news@laposte.net>
Date2018-03-01 21:51 +0100
Message-ID<p79p54$l2c$1@dont-email.me>
In reply to#38090
On 2018-03-01 21:15, Eric Douglas wrote:
> On Thursday, March 1, 2018 at 2:03:47 PM UTC-5, Andreas Leitgeb wrote:
>> [.] only matches a literal dot. That might be the root-cause of why it's
>> not working the way you like.
>>
> The Pattern says the dot matches anything (...)

Not as a character class (the thing between the square brackets).

-- 
DF.

[toc] | [prev] | [next] | [standalone]


#38094

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-03-01 13:36 -0800
Message-ID<70327dd0-6dca-48eb-804b-c3ff542a85d7@googlegroups.com>
In reply to#38093
On Thursday, March 1, 2018 at 3:51:59 PM UTC-5, Daniele Futtorovic wrote:
> >>
> > The Pattern says the dot matches anything (...)
> 
> Not as a character class (the thing between the square brackets).
> 
> -- 
> DF.

The documentation didn't seem clear to me.  I tried every parameter combination I could think of, with and without the brackets, with and without parentheses..
I'm not sure why that one looking for blank spaces seems to work, what exactly the syntax is for that ?<=\\G which didn't do anything when I put any version of it in the second one I'm trying to fix.

[toc] | [prev] | [next] | [standalone]


#38097

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-03-01 16:59 -0500
Message-ID<p79t37$c6r$1@gioia.aioe.org>
In reply to#38094
On 3/1/2018 4:36 PM, Eric Douglas wrote:
> On Thursday, March 1, 2018 at 3:51:59 PM UTC-5, Daniele Futtorovic wrote:
>>> The Pattern says the dot matches anything (...)
>>
>> Not as a character class (the thing between the square brackets).
 >
> The documentation didn't seem clear to me.

The docs say:

<quote>
Character Classes
...
Note that a different set of metacharacters are in effect inside a 
character class than outside a character class. For instance, the 
regular expression . loses its special meaning inside a character class, 
while the expression - becomes a range forming metacharacter.
</quote>

Arne

[toc] | [prev] | [next] | [standalone]


#38096

FromAndreas Leitgeb <avl@logic.at>
Date2018-03-01 21:55 +0000
Message-ID<slrnp9gtn0.5mg.avl@logic.at>
In reply to#38090
Eric Douglas <e.d.programmer@gmail.com> wrote:
> On Thursday, March 1, 2018 at 2:03:47 PM UTC-5, Andreas Leitgeb wrote:
>> [.] only matches a literal dot. That might be the root-cause of why it's
>> not working the way you like.
> The Pattern says the dot matches anything, but I tried many many variations.

I leave it to you, to write some test prog trying to replace all "[.]"
by e.g. "_", and doing that on a string like "abc.def.123".

Once you then go on to replace all the "[.]" by simple "." in your RE (there
were two of them, iirc), then you might indeed still see an unwanted result,
but maybe, looking at that new one might hint you towards the next mistake.

If it doesn't, feel free to post a followup with the updated pattern, 
in, spec and out strings.

[toc] | [prev] | [next] | [standalone]


#38098

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-03-01 14:00 -0800
Message-ID<8c677118-8115-409d-8d3b-396e54b063ae@googlegroups.com>
In reply to#38096
On Thursday, March 1, 2018 at 4:55:58 PM UTC-5, Andreas Leitgeb wrote:
> 
> I leave it to you, to write some test prog trying to replace all "[.]"
> by e.g. "_", and doing that on a string like "abc.def.123".
> 
> Once you then go on to replace all the "[.]" by simple "." in your RE (there
> were two of them, iirc), then you might indeed still see an unwanted result,
> but maybe, looking at that new one might hint you towards the next mistake.
> 
> If it doesn't, feel free to post a followup with the updated pattern, 
> in, spec and out strings.

That was just one of many tests, if you noticed the other one didn't work any better.
 input.replaceAll( "((?:" + match + "){" + (n - 1) + "})(" + match + ")", "$1" + rep );

[toc] | [prev] | [next] | [standalone]


#38099

FromAndreas Leitgeb <avl@logic.at>
Date2018-03-01 22:31 +0000
Message-ID<slrnp9gvpc.5mg.avl@logic.at>
In reply to#38098
Eric Douglas <e.d.programmer@gmail.com> wrote:
> On Thursday, March 1, 2018 at 4:55:58 PM UTC-5, Andreas Leitgeb wrote:
>> If it doesn't, feel free to post a followup with the updated pattern, 
>> in, spec and out strings.
> That was just one of many tests, if you noticed the other one didn't work any better.
>  input.replaceAll( "((?:" + match + "){" + (n - 1) + "})(" + match + ")", "$1" + rep );

It's pretty normal that some attempt at writing an RE to solve a problem
doesn't work at first time.

Then, there's essentially two strategies:

 1) randomly shuffle around the funny symbols and see if that
      works then.  If the reshuffled variant doesn't work, either,
      go back to original and defend it: "tried other way, but 
      didn't work any better."

 2) analyze what the RE is really doing, and refine it to do
      what you want it to do.

take your choice...


Also you're playing it the hard way, by building up your RE from 
fixed and variable parts. Start with constructing the RE for a specific
char and n (literally writing "{2}" (for n==3)), and only after that
works, then take it apart and assemble it from literal and variable parts.
It's one thing to get an RE right, but a much harder thing to get some
mix of RE and Java-expressions right from scratch.

PS: in the example you gave this time you do not seem to allow other
stuff between the matches.  It would match "bbb" and turn it to "bb_",
but wouldn't match "babab", so couldn't turn that to "baba_"

[toc] | [prev] | [next] | [standalone]


#38100

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-03-01 17:52 -0500
Message-ID<p7a07l$h4g$1@gioia.aioe.org>
In reply to#38099
On 3/1/2018 5:31 PM, Andreas Leitgeb wrote:
> It's pretty normal that some attempt at writing an RE to solve a problem
> doesn't work at first time.
> 
> Then, there's essentially two strategies:
> 
>   1) randomly shuffle around the funny symbols and see if that
>        works then.  If the reshuffled variant doesn't work, either,
>        go back to original and defend it: "tried other way, but
>        didn't work any better."
> 
>   2) analyze what the RE is really doing, and refine it to do
>        what you want it to do.
> 
> take your choice...
> 
> Also you're playing it the hard way, by building up your RE from
> fixed and variable parts. Start with constructing the RE for a specific
> char and n (literally writing "{2}" (for n==3)), and only after that
> works, then take it apart and assemble it from literal and variable parts.
> It's one thing to get an RE right, but a much harder thing to get some
> mix of RE and Java-expressions right from scratch.

RE are great for some things, but there are also cases where they
are not good.

Famous quote:

<quote>
Some people, when confronted with a problem, think "I know, I'll use 
regular expressions." Now they have two problems.
</quote>

Arne

[toc] | [prev] | [next] | [standalone]


#38101

FromAndreas Leitgeb <avl@logic.at>
Date2018-03-02 00:14 +0000
Message-ID<slrnp9h5rf.5mg.avl@logic.at>
In reply to#38100
Arne Vajhøj <arne@vajhoej.dk> wrote:
><quote>
> Some people, when confronted with a problem, think "I know, I'll use 
> regular expressions." Now they have two problems.
></quote>

"So if you are confronted with a problem and say, ‘I shall use the
Proverb of the Two Problems’, you now have two problems."

(from http://thecodelesscode.com/case/121 )

[toc] | [prev] | [next] | [standalone]


#38102

FromKiwi User <martin@mydomain.invalid>
Date2018-03-02 00:43 +0000
Message-ID<p7a6n9$tal$1@news.albasani.net>
In reply to#38099
On Thu, 01 Mar 2018 22:31:08 +0000, Andreas Leitgeb wrote:

> It's pretty normal that some attempt at writing an RE to solve a problem
> doesn't work at first time.
> 
> Then, there's essentially two strategies:
> 
>  1) randomly shuffle around the funny symbols and see if that
>       works then.  If the reshuffled variant doesn't work, either,
>       go back to original and defend it: "tried other way, but didn't
>       work any better."
> 
>  2) analyze what the RE is really doing, and refine it to do
>       what you want it to do.
> 
> take your choice...
>
Another way to test regexes may help: use an online regex test tool like 
this one:
 
http://www.regexplanet.com/advanced/java/index.html 

It helps because it:
- tests an expression without you writing anything except the regex
- lets you submit a set of test strings and run repeated tests against
  them
- has check boxes for making caseless comparisons, etc.


-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38103

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-03-01 19:49 -0500
Message-ID<p7a72k$qqd$1@gioia.aioe.org>
In reply to#38102
On 3/1/2018 7:43 PM, Kiwi User wrote:
> On Thu, 01 Mar 2018 22:31:08 +0000, Andreas Leitgeb wrote:
>> It's pretty normal that some attempt at writing an RE to solve a problem
>> doesn't work at first time.
>>
>> Then, there's essentially two strategies:
>>
>>   1) randomly shuffle around the funny symbols and see if that
>>        works then.  If the reshuffled variant doesn't work, either,
>>        go back to original and defend it: "tried other way, but didn't
>>        work any better."
>>
>>   2) analyze what the RE is really doing, and refine it to do
>>        what you want it to do.
>>
>> take your choice...
>>
> Another way to test regexes may help: use an online regex test tool like
> this one:
>   
> http://www.regexplanet.com/advanced/java/index.html
> 
> It helps because it:
> - tests an expression without you writing anything except the regex
> - lets you submit a set of test strings and run repeated tests against
>    them
> - has check boxes for making caseless comparisons, etc.

Yes.

But if the regex is so complicated/unreadable that it is not obvious
whether it works or not, then I would question whether regex is the
right choice.

Arne

[toc] | [prev] | [next] | [standalone]


#38105

FromKiwi User <martin@mydomain.invalid>
Date2018-03-02 01:33 +0000
Message-ID<p7a9ke$tal$2@news.albasani.net>
In reply to#38103
On Thu, 01 Mar 2018 19:49:26 -0500, Arne Vajhøj wrote:

> On 3/1/2018 7:43 PM, Kiwi User wrote:
>> On Thu, 01 Mar 2018 22:31:08 +0000, Andreas Leitgeb wrote:
>>> It's pretty normal that some attempt at writing an RE to solve a
>>> problem doesn't work at first time.
>>>
>>> Then, there's essentially two strategies:
>>>
>>>   1) randomly shuffle around the funny symbols and see if that
>>>        works then.  If the reshuffled variant doesn't work, either, go
>>>        back to original and defend it: "tried other way, but didn't
>>>        work any better."
>>>
>>>   2) analyze what the RE is really doing, and refine it to do
>>>        what you want it to do.
>>>
>>> take your choice...
>>>
>> Another way to test regexes may help: use an online regex test tool
>> like this one:
>>   
>> http://www.regexplanet.com/advanced/java/index.html
>> 
>> It helps because it:
>> - tests an expression without you writing anything except the regex -
>> lets you submit a set of test strings and run repeated tests against
>>    them
>> - has check boxes for making caseless comparisons, etc.
> 
> Yes.
> 
> But if the regex is so complicated/unreadable that it is not obvious
> whether it works or not, then I would question whether regex is the
> right choice.
>
Yes - but surely that should go without saying. Choosing the right tool 
for a job is an essential part of the programmer's trade.

The point I was trying to make wasn't specifically about the regex in 
question, but that there are often more convenient ways of testing and/or 
developing regexes than trying to do it in situ.

For instance, I regularly develop my own rules for Spamassassin, which is 
written in Perl and uses Perl regexes as an essential part of its spam 
recognition rules. grep, a commonly used file scanning tool in Linux and 
other Unices uses regexes to select which input lines should be output. 
Its -P option tells it to use the Perl regex dialect rather than its own, 
making it very easy to use when developing a Perl regex. Just create a 
file containing example strings arranged one per line and with each line 
annotated to show whether the string should match or not. Then run the 
regex against the file:

  grep -P 'perlRegex' testfile.txt

to show matching lines and

  grep -PV 'perlRegex' testfile.txt

to show non-matching lines. In these examples I quotes the regexes  
to stop the command shell from modifying the regex.

Since there's no equivalent way of testing Java regexes, there's no 
reason why you shouldn't write a simple Java command line program that 
would do exactly the same: accepting the regex as a parameter, applying 
it to every line in a test file and displaying the matches. 

However, given that the Java regex test page is there to be used, why not 
use it?


-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38108

FromArne Vajhøj <arne@vajhoej.dk>
Date2018-03-02 13:00 -0500
Message-ID<p7c3fe$2qs$1@gioia.aioe.org>
In reply to#38105
On 3/1/2018 8:33 PM, Kiwi User wrote:
> On Thu, 01 Mar 2018 19:49:26 -0500, Arne Vajhøj wrote:
>> On 3/1/2018 7:43 PM, Kiwi User wrote:
>>> Another way to test regexes may help: use an online regex test tool
>>> like this one:
>>>    
>>> http://www.regexplanet.com/advanced/java/index.html
>>>
>>> It helps because it:
>>> - tests an expression without you writing anything except the regex -
>>> lets you submit a set of test strings and run repeated tests against
>>>     them
>>> - has check boxes for making caseless comparisons, etc.
>>
>> Yes.
>>
>> But if the regex is so complicated/unreadable that it is not obvious
>> whether it works or not, then I would question whether regex is the
>> right choice.
>>
> Yes - but surely that should go without saying. Choosing the right tool
> for a job is an essential part of the programmer's trade.
> 
> The point I was trying to make wasn't specifically about the regex in
> question, but that there are often more convenient ways of testing and/or
> developing regexes than trying to do it in situ.

Yes. But my argument is that:
- the whole point of regex is that it is a compact and easy to read way
   to do some advanced text stuff
- if the regex is long and not easy to read then something else is
   probably more easy to read
- having to use tools to test if the regex does what one think it
   does seems to be a good indication that it is not easy to read

Sometimes regex can be combined with a break up in code.

Splitting string without regex and then use simple regex on some of the
parts or doing a high level split with simple regex and more detailed
split using code are sometimes good choices.

Arne

[toc] | [prev] | [next] | [standalone]


#38114

FromKiwi User <martin@mydomain.invalid>
Date2018-03-03 20:07 +0000
Message-ID<p7evak$2c2$1@news.albasani.net>
In reply to#38108
On Fri, 02 Mar 2018 13:00:13 -0500, Arne Vajhøj wrote:

> Yes. But my argument is that:
> - the whole point of regex is that it is a compact and easy to read way
>    to do some advanced text stuff
> - if the regex is long and not easy to read then something else is
>    probably more easy to read
> - having to use tools to test if the regex does what one think it
>    does seems to be a good indication that it is not easy to read
>
Fair enough. I very rarely use regexes except as matchers and almost 
never for the sort of thing Eric is trying to do. In that case I'm far 
more likely to use one of the text parsing classes, though these often 
use regexes to decide what might be a keyword or separator.

> Splitting string without regex and then use simple regex on some of the
> parts or doing a high level split with simple regex and more detailed
> split using code are sometimes good choices.
>
+1

In practise I use regexes far more frequently in SpamAssassin (a Perl 
application) or in awk scripts than I do in Java or C programs, and if 
its a really complex task I'll use Coco/R to generate Java from a BNF 
definition.
  

-- 
Martin    | martin at
Gregorie  | gregorie dot org

[toc] | [prev] | [next] | [standalone]


#38106

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-03-02 05:40 -0800
Message-ID<5e445e98-76e9-4feb-9955-035a6c5a2ed5@googlegroups.com>
In reply to#38099
On Thursday, March 1, 2018 at 5:31:28 PM UTC-5, Andreas Leitgeb wrote:
>  2) analyze what the RE is really doing, and refine it to do
>       what you want it to do.
> 
> take your choice...

Therein lies the problem.  I analyzed the RE and apparently have no understanding of what it's doing.

I found where someone on the internet solved a similar problem and this solution seems to work.  This expression as far as I can tell does successfully replace every third whitespace, ignoring every other character.
out = in.replaceAll("(?<=\\G\\S*\\s\\S*\\s\\S*)\\s", "_");

So I try that, and get nothing.  My output looks exactly the same as my input, but why?
out = in.replaceAll("(?<=\\G.*b.*)b", "_");

The documentation on that says:
(?<=X)	X, via zero-width positive lookbehind
 (not sure what this did for the original expression here)
\G	The end of the previous match
 (this is what I expect replaceAll to always do)
\S	A non-whitespace character: [^\s]
\s	A whitespace character: [ \t\n\x0B\f\r]
X*	X, zero or more times
.	Any character (may or may not match line terminators)

Any character includes whitespace?  Why does my modified expression not replace every other "b"?

[toc] | [prev] | [next] | [standalone]


#38107

FromAndreas Leitgeb <avl@logic.at>
Date2018-03-02 17:46 +0000
Message-ID<slrnp9j3ev.5mg.avl@logic.at>
In reply to#38106
Eric Douglas <e.d.programmer@gmail.com> wrote:
> out = in.replaceAll("(?<=\\G.*b.*)b", "_");

You might have noticed that the original RE (with spaces) uses
\s and \S, and that any single character can only *either* be
matched by \s *or* by \S. You can consider \S to be the opposite
of \s.

The opposite of b isn't ".", but rather "[^b]".

Note, that if "b" really should be a possibly longer string, 
then it's "opposite" will quickly become very ugly with
increasing length. That would be a case were you'd better
pick an alternative without REs.

So, by correcting the "." to "[^b]", you get:
out = in.replaceAll("(?<=\\G[^b]*b[^b]*)b", "_");
and to that you can now add the extra pair of non-
capturing parens and e.g. "{2}" for n=3 .

> The documentation on that says:
> (?<=X)	X, via zero-width positive lookbehind
>  (not sure what this did for the original expression here)

It makes sure that the "\\G[^b]*b[^b]*" is *not* part of the
thing to replace, yet required to exist before the actual match.

Your own approach of capturing the "prefix" with parens and
substing it into the replacement via $1 looks much cleaner
to me, btw.

> \G	The end of the previous match
>  (this is what I expect replaceAll to always do)

Well, nope.  if you do a "ababab".replaceAll("b","_"); you'd
want all "b"s replaced, even if not adjacent to the previous
one.

> \S	A non-whitespace character: [^\s]
> \s	A whitespace character: [ \t\n\x0B\f\r]
> X*	X, zero or more times
> .	Any character (may or may not match line terminators)
>
> Any character includes whitespace?  Why does my modified
> expression not replace every other "b"?

The problem here is, that the "b"s of input string are *also*
matched by the ".*", so each single match is likely a bit longer
than you expect it to be. I'm pretty sure that it still *did*
replace the very last "b".

[toc] | [prev] | [next] | [standalone]


#38109

FromEric Douglas <e.d.programmer@gmail.com>
Date2018-03-02 10:38 -0800
Message-ID<9730d36c-f472-4b7f-9edb-deedc1630868@googlegroups.com>
In reply to#38107
On Friday, March 2, 2018 at 12:46:22 PM UTC-5, Andreas Leitgeb wrote:
> The opposite of b isn't ".", but rather "[^b]".
> 
> Note, that if "b" really should be a possibly longer string, 
> then it's "opposite" will quickly become very ugly with
> increasing length. That would be a case were you'd better
> pick an alternative without REs.
> 
> So, by correcting the "." to "[^b]", you get:
> out = in.replaceAll("(?<=\\G[^b]*b[^b]*)b", "_");
> and to that you can now add the extra pair of non-
> capturing parens and e.g. "{2}" for n=3 .
> 

Nope, see what I mean?  Apparently not intuitive.
out = in.replaceAll("(?<=\\G[^b]*b[^b]*)b", "_");
still getting output exactly the same as the input.

> Well, nope.  if you do a "ababab".replaceAll("b","_"); you'd
> want all "b"s replaced, even if not adjacent to the previous
> one.
> 

Maybe it's just me, but "end of previous" was not clear.  If you're search the "ababab" string and you're looking for "bab" can it find it twice?
replaceAll("bab","_") could find and replace then look from there, and you end up with "a_ab", or could replace every match and you get either "a_" or "a__".  If the "a_ab" is the default functionality, I don't understand what the \\G does.

[toc] | [prev] | [next] | [standalone]


#38110

FromAndreas Leitgeb <avl@logic.at>
Date2018-03-02 20:15 +0000
Message-ID<slrnp9jc7f.5mg.avl@logic.at>
In reply to#38109
Eric Douglas <e.d.programmer@gmail.com> wrote:
> Nope, see what I mean?  Apparently not intuitive.
> out = in.replaceAll("(?<=\\G[^b]*b[^b]*)b", "_");
> still getting output exactly the same as the input.

It really seems to me now as if Java (1.8.0_131 here) was just buggy here:

"abaabaaabaaaabaaaaabaaaaaabxbb".replaceAll( "(?<=\G[^b]*b[^b]*b[^b]*)b", "_");

works, while

"abaabaaabaaaabaaaaabaaaaaabxbb".replaceAll( "(?<=\G[^b]*b[^b]*)b", "_");

doesn't.

The apparent "pattern" is, that adding "b[^b]*" will alternate between
working and not working.

Using {2} in a (?<=...) doesn't seem to work at all --
  "Look-behind group does not have an obvious maximum length ..."

Anyway:

   out = in.replaceAll( "([^b]*b[^b]*)[b]" , "$1_");

seems to work just fine, and:

   out = in.replaceAll( "([^b]*(b[^b]*){2})b" , "$1_");

only replaces every third b.

Imho, that's one STRONG argument for the simpler approach.

>> Well, nope.  if you do a "ababab".replaceAll("b","_"); you'd
>> want all "b"s replaced, even if not adjacent to the previous
>> one.
> Maybe it's just me, but "end of previous" was not clear.
> If you're search the "ababab" string and you're looking for "bab"
> can it find it twice?

Nope, but in  "babababa", if you search for \\Gbab you'll get only 
one match, because the second match is not adjacent to the first one.

Without the \\G, the next match *may* still start adjacent ("babbab"),
but *may* also start later ("babxyzbab").

Under no circumstances(*) will the second match overlap a previous one.

*: except, of course, when Java's RE impl is buggy. Then all bets are off.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.java.programmer


csiph-web