3

What regular expression should I use with the 'replace()' function in JavaScript to change every occurrence of char '_' in 0, but stop working as long as finding the char '.'?

Example:

_____323.____ ---> 00323._

____032.0____ --> 0032.0_

Are there ways more efficient than to use 'replace()'?

I am working with numbers. In particular, they can be both integer that float, so my string could never have two dots like in __32.12.32 or __31.34.45. At maximum just one dot.

What can I add in this:

/_(?=[\d_.])/g

to also find '_' followed by nothing?

Example: 0__ or 2323.43_

This does not work:

/_(?=[\d_.$])/g
6
  • You can use replace() along with reg-ex, what is your choice? Commented Sep 3, 2013 at 13:35
  • @dystroy sorry, i dropped my comment before seeing yours and your answer. Commented Sep 3, 2013 at 13:38
  • Is there always a period? Commented Sep 3, 2013 at 13:41
  • @JasonMcCreary I understand "they can be both integer that float [...] At maximum just one dot" as a NO. Commented Sep 3, 2013 at 13:56
  • Given that _032.0_ is possible, why isn't _032._0 possible ? Commented Sep 3, 2013 at 16:12

5 Answers 5

8

You could use

str = str.replace(/[^.]*/,function(a){ return a.replace(/_/g,'0') })

Reference

Sign up to request clarification or add additional context in comments.

5 Comments

Can you explain how replace works when 2nd parameter is a function?
@Jongware I know how that works actually, I wanted it to make it a better answer since it is a smart one.
@UmurKontacı I added the reference.
very nice usage of the global flag ( when is not present) +1
1

Without replace/regex:

var foo = function (str) {
  var result = "", char, i, l;
  for (i = 0, l = str.length; i < l; i++) {
    char = str[i];
    if (char == '.') {
      break;
    } else if (char == '_') {
      result += '0';
    } else {
      result += str[i];
    }
    char = str[i];
  }
  return result + str.slice(i);
}

With regex: dystroy

Benchmark for the various answers in this post: http://jsperf.com/regex-vs-no-regex-replace

9 Comments

Non-regex needn't be that large an answer: var str = "__323.__345._"; var newstr = str.substr(0,str.indexOf('.')).replace(/_/g,'0')+str.substr(str.indexOf('.'));
@SmokeyPHP There's a regex in your comment.
@dystroy Funny.. yes of course - I mean of course a solution that takes most of the effort away from the regex (my tests prove up to 2x performance increase)
@Aegis That's fab, thanks for getting involved and all, but I meant against the regex solution provided by dystroy.
@SmokeyPHP I know, I'll add that to the test. My point is just that if you want performance then avoiding regex is a good idea, even just one :p
|
1

Unless you have some other obscure condition -

find:

 _(?=[\d_.])

replace:

 0

Or "To find also _ followed by nothing, example: 0__ or 2323.43_"

_(?=[\d_.]|$)

Comments

0

You could use lookahead assertion in regex...

"__3_23._45_4".replace(/_(?![^.]*$)/g,'0')

Result: 003023._45_4

Explanation:

/          # start regex
_          # match `_`
(?!        # negative lookahead assertion
[^.]*$     # zero or more (`*`) not dots (`[^.]`) followed by the end of the string
)          # end negative lookahead assertion
/g         # end regex with global flag set

3 Comments

Note: fails on __323.__345._ (if that situation were to crop up)
As for me, it stops only before the last . character, ignoring all previous (replacing undescores).
That don't work even in Python: re.sub(r'_(?![^.]*$)', "0", "__3_23._45_4._5") result: '003023.04504._5'
0
var str = "___345_345.4w3__w45.234__34_";

var dot = false;
str.replace(/[._]/g, function(a){
  if(a=='.' || dot){
    dot = true;
    return a
  } else {
    return 0
  }
})

1 Comment

About your str : "At maximum just one dot".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.