Long story short, i would like to get the parameters list from JavaScript methods in Java. It works well if i got any parameters, but if the parameter list is empty it's just not working.
For example
function() { return fn.num(tra.getMaster_id(fg)+1)
My regular expression is:
(?<=\({1}).*?(?=\){1})
The result i get:
tra.getMaster_id(fg
The result i want is the empty space between the ().
If i test it with Here everything is fine, but in java it didn't working yet :(
I would appreciate any ideas!
First of all, you don't need {1} repetition quantifiers, everything is repeated just once by default. Secondly, since regexes in java are just strings that get interpreted, you have to escape escaping slashes (\):
(?<=\\().*?(?=\\))
Thirdly, you are getting the match that you want, it is just that there are more than one matches in this case. You are currently fetching the last one and not the first one.
Related
I was looking at JSON data that was just in a text file. I don't want to do anything aside from just use regex to get the values in between quotes. I'm just using this as a way to help practice regex and got to this point that seems like it should be simple, but it turns out it's not (at least to me and a few other people at the office). I've matched complicated urls with ease in regex so I'm not completely new to regex. This just seems like a weird case for me.
I've tried:
/(?:")(.*?)(?:")/
/"(.*?)"/
and several others but these got me the closest.
Basically we can forget that it's JSON and just say I want to match the words value and stuff out of "value" and "stuff". Everything I try includes the quotes, so I'd have to clean the strings afterwards of the delimiters or else the string is literally "value" with the quotes.
Any help would be much appreciated, whether this is simple or complicated, I'd love to know! Thanks
Update: Alright so I think I'll go with (?<=")(.*?)(?=") and read things by line without the global setting on so I just get the first match on each line. In my code I was just plopping in a huge string into a var in the code instead of actually opening a file with ajax/filereader or having a form setup to input data. I think I'll mark this as solved, much appreciated!
You have two choices to solve this problem:
Use capturing groups
You can match the delimiters and use capturing groups to get the text within. In this case your two regexes will work, but you need to use access capturing group 1 to get the results (demo). See How do you access the matched groups in a JavaScript regular expression? for how to do that.
Use zero-width assertions
You can use zero-width assertions to match only the text within, require delimiters around them without actually matching them (demo):
(?<=")(.*?)(?=")
but now since I'm not consuming the quotes it'll find instances between each quote, not just between pairs of quotes: e.g., a"b"c" would find b and c.
As for getting just the first match, I think that'll happen by default in JavaScript. You'd have to ask for repeated matching before you see the subsequent ones. So if you process your file one line at a time, you should get what you want.
get the values in between quotes
One thing to keep in mind is that valid JSON accepts escaped quotes inside the quoted values. Therefore, the RegEx should take this into account when capturing the groups which is done with the “unrolling-the-loop” pattern.
var pattern = /"[^"\\]*(?:\\.[^"\\]*)*"/g;
var data = {
"value": "This is \"stuff\".",
"empty": "",
"null": null,
"number": 50
};
var dataString = JSON.stringify(data);
console.log(dataString);
var matched = dataString.match(pattern);
matched.map(item => console.log(JSON.parse(item)));
I had an issue where String arguments were being truncated to the first character in our g:message tags (longs/integers seemed to be fine).
Ultimately, I figured out we were not calling g:message syntactically correct from within Javascript so some minor tweaks fixed the issue. Problem is - I don't understand why the former doesn't work.
Can anyone describe what was happening here?
jQuery("#myId").html("<g:message code='domain.message.path' args="${command?.foo?.name}"/>"); //incorrect, only displays first character of message
jQuery("#myId").html("${g.message(code: 'domain.message.path', args: [command?.foo?.name])}"); //correct, displays full string
I assume you're rendering this as part of a .gsp page? Here's the thing. In the first one, you're nesting quotes, essentially leaving the ${} section out of the string. Even Stackoverflow can tell; note how that part is a different color:
jQuery("#myId").html("<g:message code='domain.message.path' args="${command?.foo?.name}"/>");
See how the quote at the end of html( is ended by the quote before ${, leaving the ${command?.foo?.name} block outside the string? If command.foo.name was the string "bob", then when this rendered, you'd get:
jQuery("#myId").html("<g:message code='domain.message.path' args="bob"/>");
You might think this looks right, but javascript will handle this poorly.
If you used single quotes for the internal string, like you do with 'domain.message.path', it should work fine:
jQuery("#myId").html("<g:message code='domain.message.path' args='${command?.foo?.name}'/>");
I'm trying to improve my understanding of Regex, but this one has me quite mystified.
I started with some text defined as:
var txt = "{\"columns\":[{\"text\":\"A\",\"value\":80},{\"text\":\"B\",\"renderer\":\"gbpFormat\",\"value\":80},{\"text\":\"C\",\"value\":80}]}";
and do a replace as follows:
txt.replace(/\"renderer\"\:(.*)(?:,)/g,"\"renderer\"\:gbpFormat\,");
which results in:
"{"columns":[{"text":"A","value":80},{"text":"B","renderer":gbpFormat,"value":80}]}"
What I expected was for the renderer attribute value to have it's quotes removed; which has happened, but also the C column is completely missing! I'd really love for someone to explain how my Regex has removed column C?
As an extra bonus, if you could explain how to remove the quotes around any value for renderer (i.e. so I don't have to hard-code the value gbpFormat in the regex) that'd be fantastic.
You are using a greedy operator while you need a lazy one. Change this:
"renderer":(.*)(?:,)
^---- add here the '?' to make it lazy
To
"renderer":(.*?)(?:,)
Working demo
Your code should be:
txt.replace(/\"renderer\"\:(.*?)(?:,)/g,"\"renderer\"\:gbpFormat\,");
If you are learning regex, take a look at this documentation to know more about greedyness. A nice extract to understand this is:
Watch Out for The Greediness!
Suppose you want to use a regex to match an HTML tag. You know that
the input will be a valid HTML file, so the regular expression does
not need to exclude any invalid use of sharp brackets. If it sits
between sharp brackets, it is an HTML tag.
Most people new to regular expressions will attempt to use <.+>. They
will be surprised when they test it on a string like This is a
first test. You might expect the regex to match and when
continuing after that match, .
But it does not. The regex will match first. Obviously not
what we wanted. The reason is that the plus is greedy. That is, the
plus causes the regex engine to repeat the preceding token as often as
possible. Only if that causes the entire regex to fail, will the regex
engine backtrack. That is, it will go back to the plus, make it give
up the last iteration, and proceed with the remainder of the regex.
Like the plus, the star and the repetition using curly braces are
greedy.
Try like this:
txt = txt.replace(/"renderer":"(.*?)"/g,'"renderer":$1');
The issue in the expression you were using was this part:
(.*)(?:,)
By default, the * quantifier is greedy by default, which means that it gobbles up as much as it can, so it will run up to the last comma in your string. The easiest solution would be to turn that in to a non-greedy quantifier, by adding a question mark after the asterisk and change that part of your expression to look like this
(.*?)(?:,)
For the solution I proposed at the top of this answer, I also removed the part matching the comma, because I think it's easier just to match everything between quotes. As for your bonus question, to replace the matched value instead of having to hardcode gbpFormat, I used a backreference ($1), which will insert the first matched group into the replacement string.
Don't manipulate JSON with regexp. It's too likely that you will break it, as you have found, and more importantly there's no need to.
In addition, once you have changed
'{"columns": [..."renderer": "gbpFormat", ...]}'
into
'{"columns": [..."renderer": gbpFormat, ...]}' // remove quotes from gbpFormat
then this is no longer valid JSON. (JSON requires that property values be numbers, quoted strings, objects, or arrays.) So you will not be able to parse it, or send it anywhere and have it interpreted correctly.
Therefore you should parse it to start with, then manipulate the resulting actual JS object:
var object = JSON.parse(txt);
object.columns.forEach(function(column) {
column.renderer = ghpFormat;
});
If you want to replace any quoted value of the renderer property with the value itself, then you could try
column.renderer = window[column.renderer];
Assuming that the value is available in the global namespace.
This question falls into the category of "I need a regexp, or I wrote one and it's not working, and I'm not really sure why it has to be a regexp, but I heard they can do all kinds of things, so that's just what I imagined I must need." People use regexps to try to do far too many complex matching, splitting, scanning, replacement, and validation tasks, including on complex languages such as HTML, or in this case JSON. There is almost always a better way.
The only time I can imagine wanting to manipulate JSON with regexps is if the JSON is broken somehow, perhaps due to a bug in server code, and it needs to be fixed up in order to be parseable.
I have an html checkbox element with the following name:
type_config[selected_licenses][CC BY-NC-ND 3.0]
I would like to break this name apart as follows and returned as part of an array:
["type_config", "[selected_licenses]", "[CC BY-NC-ND 3.0]", "[selected_licenses][CC BY-NC-ND 3.0]"]
I thought I could do this by using a regular expression in javascript. Here is the expression that I am using:
matches = /([a-zA-Z0-9_]*)((\[[a-zA-Z0-9_\.\s]*\])+)*/.exec(element_name);
but this is the result I am getting in my matches variable:
["type_config[selected_licenses]", "type_config", "[selected_licenses]", "[selected_licenses]", index: 0, input: "type_config[selected_licenses][CC BY-ND 3.0]"]
I am half way there. What am I doing wrong in my regular expression? I guess I should also ask if it is possible to accomplish what I want with a regex?
Thanks.
The problem with this kind of goal is that there's no simple way to achieve this with regular expression, i.e. a simple match call. In short, even if you put a quantifier after a capturing group, the captured string will always be just one.
You'll have to rely on something more specific, like breaking the string with a repeated use of indexOf, or something like
name.split(/(?=\[)/);
Maybe you want to be sure that name is formally correct.
This is a very ugly problem. I don't know how repeatable this is, but I can do it:
Regex
^(\w+)(?<firstbracket>\[(?<secondbracket>[^]]*)\]\[(.*?)\])$
Replacement
["$1", "[$3]", "[$4]", "$2"]
Demo
http://regex101.com/r/eD9mH8
I have made this regular expression which does exactly what I want when I test it in e.g. RegExr:
^https?:\/\/(www\.)?(test\.yahoo\.com|sub\.yahoo\.com)?(?!([a-z0-9]+\.)?(localhost|yahoo\.com))(.*)?
However when I test it in javascript it says that the expression is invalid. After hours of debugging I found out that this expression works in javascript:
^https?:\/\/(www\.)?(test\.yahoo\.com|sub\.yahoo\.com)?(?![a-z0-9]+\.)?(localhost|yahoo\.com)(.*)?
However this doesn't do what I want (again testing in RegExr).
Why cannot I use the first expression in javascript? And how do I fix it?
UPDATE JULY 25
Sorry for the lack of info. The way I am using the Regexp is through a jQuery extension which lets me select using regexp. The script can be seen here: http://james.padolsey.com/javascript/regex-selector-for-jquery/
The specific code I am trying to get to work is:
$('a:regex(href, ^https?:\/\/(www\.)?(test\.yahoo\.com|sub\.yahoo\.com)?(?!([a-z0-9]+\.)?(localhost|yahoo\.com))(.*)?)').live('click', function(e) {
After including the linked jQuery plugin. The text strings I am testing are:
http://yahoo.com
http://google.dk
http://subdomain.yahoo.com
http://test.yahoo.com
http://localhost.dk
http://sub.yahoo.com/lalala
Where it is supposed to match "http://google.dk", "http://test.yahoo.com" and "http://sub.yahoo.com/lalala" - which it does when using RegExr but failing (invalid expression) using the jQuery plugin.
The first regular expression is not invalid:
var regexp = /^https?:\/\/(www\.)?(test\.yahoo\.com|sub\.yahoo\.com)?(?!([a-z0-9]+\.)?(localhost|yahoo\.com))(.*)?/;
works fine.
If you want to instantiate the expression from a string, you have to double all the backslashes:
var regexp = new RegExp("^https?:\\/\\/(www\\.)?(test\\.yahoo\\.com|sub\\.yahoo\\.com)?(?!([a-z0-9]+\\.)?(localhost|yahoo\\.com))(.*)?");
When you start from a string, you have to account for the fact that the string constant itself uses backslashes as a quoting mechanism, so there will be two evaluations made: one as a string, and one as a regular expression.
edit — OK I think I see the problem. That plugin you're trying to use is simply attempting to do something that's just not going to work, given the way that Sizzle parses selectors. In other words, the problem is not with your regular expression, it's with the overall selector. It is not even getting far enough to parse the regular expression.
Specifically it seems to be nested parentheses inside the regular expression. Something as simple as
$('a:regex(href, ((abc)))')
causes an error. You can instead do something like this:
$('a').filter(function() {
return /^https?:\/\/(www\.)?(test\.yahoo\.com|sub\.yahoo\.com)?(?!([a-z0-9]+\.)?(localhost|yahoo\.com))(.*)?/.test(this.href);
}).whatever( ... );