views:

87

answers:

8

I have found the following expression which is intended to modify the id of a cloned html element e.g. change contactDetails[0] to contactDetails[1]:

var nel = 1;
var s = $(this).attr(attribute);
    s.replace(/([^\[]+)\[0\]/, "$1["+nel+"]");
    $(this).attr(attribute, s);

I am not terribly familiar with regex, but have tried to interpret it and with the help of The Regex Coach however I am still struggling. It appears that ([^\[]+) matches one or more characters which are not '[' and \[0\]/ matches [0]. The / in the middle I interpret as an 'include both', so I don't understand why the author has even included the first expression.

I dont understand what the $1 in the replace string is and if I use the Regex Coach replace functionality if I simply use [0] as the search and [1] as the replace I get the correct result, however if I change the javascript to s.replace(/\[0\]/, "["+nel+"]"); the string s remains unchanged.

I would be grateful for any advice as to what the original author intended and help in finding a solution which will successfully replace the a number in square brackets anywhere within a search string.

+2  A: 

The $1 is a backreference to the first group in the regex. Groups are the pieces inside (). So, in this case $1 will be replaced by whatever the ([^\[]+) part matched.

If the string was contactDetails[0] the resulting string would be contactDetails[1].

Note that this regex only replaces 0s inside square brackets. If you want to replace any number you will need something like:

([^\[]+)\[\d+\]

The \d matches any digit character. \d+ then becomes any sequence of at least one digit.

But your code will still not work, because Javascript strings are immutable. That means they can't be changed once created. The replace method returns a new string, instead of changing the original one. You should use:

s = s.replace(...)
Martinho Fernandes
Thanks, I understand now an therefore understand that this should be working, however it is not. I have extracted this code and altering to set var s = ContactData[0], I've place it into a vanila html file within a script block, but after the replace s is unchanged. Any ideas what is happening?
Richbits
when you say `s = ContactData[0]`, you mean `s = "ContactData[0]"` right? It's the string whose contents are `ContactData[0]` not the value at index 0 of the `ContactData[0]` array?
Martinho Fernandes
Addendum: ... of the `ContactData` array
Martinho Fernandes
Sorry yes you are correct and I had included the "" within my code.
Richbits
See my edit. It should work now.
Martinho Fernandes
+1  A: 

looks like it replaces arrays of 0 with 1.

For example:   array[0] goes to array[1]

Explanation:

([^[]+) - This part means save everything that is not a [ into variable $1
[0]/     - This part limits Part 1 to save everything up to a [0]

"$1["+nel+"]" - Print out the contents of $1 (loaded from part 1) and add the brackets with the value of nel. (in your example nel = 1)

RC
A: 

Square braces define a set of characters to match. [abc] will match the letters a, b or c.

By adding the carat you are now specifying that you want characters not in the set. [^abc] will match any character that is not an a, b or c.

Because square braces have special meaning in RegExps you need to escape them with a slash if you want to match one. [ starts a character set, \[ matches a brace. (Same concept for closing braces.)

So, [^\[]+ captures 1 or more characters that are not [.

Wrapping that in parenthesis "captures" the matched portion of the string (in this case "contactDetails" so that you can use it in the replacement.

$1 uses the "captured" string (i.e. "contactDetails") in the replacement string.

Prestaul
A: 

This regex matches "something" followed by a [0].
"something" is identified by the expression [^\[]+ which matches all charactes that are not a [. You can see the () around this expression, because the match is reused with $1, later. The rest of your regex - that is \[0\] just matches the index [0]. The author had to write \[ and \] because [ and ] are special charactes for regular expressions and have to be escaped.

tanascius
A: 

$1 is a reference to the value of the first paranthesis pair. In your case the value of

[^\[]+

which matches one or more characters which are not a '['

The remaining part of the regexp matches string '[0]'.

So if s is 'foobar[0]' the result will be 'foobar[1]'.

sebasgo
A: 

[^\[] will match any character that is not [, the '+' means one or more times. So [^[]+ will match contactDetails. The brackets will capture this for later use. The '\' is an escape symbol so the end \[0\] will match [0]. The replace string will use $1 which is what was captured in the brackets and add the new index.

slashnick
A: 

Your interpretation of the regular expression is correct. It is intended to match one or more characters which are not [, followed by a literal [0]. And used in the replace method, the match would be replaced with the match of the first grouping (that’s what $1 is replaced with) together with the sequence [ followed by the value of nel and ] (that’s how "$1["+nel+"]" is to be interpreted).

And again, a simple s.replace(/\[0\]/, "["+nel+"]") does the same. Except if there is nothing in front of [0], because in that case the first regex wouldn’t find a match.

Gumbo
+2  A: 

Find

/           # Signifies the start of a regex expression like " for a string
([^\[]+)    # Capture the character that isn't [ 1 or more times into $1
\[0\]       # Find [0]
/           # Signifies the end of a regex expression

Replace

"$1["       # Insert the item captured above And [
+nel+       # New index
"]"         # Close with ]

To create an expression that captures any digit, you can replace the 0 with \d+ which will match a digit 1 or more times.

s.replace(/([^\[]+)\[\d+\]/, "$1["+nel+"]");
Gavin Miller
Thanks, really nice explanation. It is not working for me though the following alerts contact[0]:var nel = 1;var s = "contact[0]";s.replace(/([^\[]+)\[\d+\]/, "$1["+nel+"]");alert(s);
Richbits
var s = s.replace(...) will do the trick. You need to assign a replace to a variable. Strings are not modified in place.
Gavin Miller
Thanks, yes that is what was wrong, thanks for your help.
Richbits
My pleasure
Gavin Miller