What is the best practice for line continuation in JavaScript? I know that you can use \ for strings. But how would you split the following code?
var statement = con.createStatement("select * from t where
(t.a1 = 0 and t.a2 >=-1)
order by a3 desc limit 1");
If I properly understood your question:
var statement = con.createStatement('select * from t where '
+ '(t.a1 = 0 and t.a2 >=-1) '
+ 'order by a3 desc limit 1');
For readability, it is fine to align + operator on each row:
Anyway, unless you're using Ecmascript 2015, avoid to split a multiline string with \, because:
It's not standard JavaScript
A whitespace after that character could generate a parsing error
I like using backslashes for JavaScript line continuation, like so:
// validation
$(".adjustment, .info input, .includesAndTiming input, \
.independentAdj, .generalAdj, .executiveAdj \
#officeExpense, #longDistanceExpense, #digitalImages, #milesReimbursment, #driveTime, #statementTranscription").keypress(function (event) {
My personal preference is similar to your first response there, but for my eyes its readability is easier:
var statement = con.createStatement
(
'select * from t where ' +
'(t.a1 = 0 and t.a2 >=-1) ' +
'order by a3 desc limit 1'
);
It strikes a close similarity to the SQL syntax format I've been using for nearly 20 years:
SELECT *
FROM t
WHERE
t.a1 = 0 AND
t.a2 >=-1
ORDER BY a3 DESC
LIMIT 1
Keeping the continuation (+ in JavaScript or AND in SQL) on the far right permits the eye to slide evenly down the left edge, checking lvalues & syntax. That's slightly more difficult to do with the continuation on the left - not important unless you do a LOT of this stuff, at which point every calorie you spend is a calorie that might've been saved by a slight improvement in format.
Since this query is so simple, breaking it all out to SQL format is wasteful of space and bandwidth, which is why the suggested JavaScript is on six lines instead of ten. Collapsing the curlies up one line each brings it to four lines, saving whitespace. Not quite as clear or as simple to edit, though.
The "+" is for concatenation of strings and most of the examples are dealing with strings. What if you have a command you need to string across multiple lines, such as a compound "if" statement? You need a backslash at the end of each line that is to be continued. This escapes the invisible next line character so that it will not delimit the command in mid statement.
Related
So I'm writing my own napkin math parser[1] for fun. Napkin math is a part of a custom text editor I am building - when you press space after an equals sign it will detect the equation prior to the equals sign and does the math for you. E.g., you type 1+1= and it kicks out the 2 for you magically so you have 1+1=2 on the screen.
I'm really struggling with getting a regex to match equations prior to the equals sign. My brain is shot and I am in desparate need of help from a lord of regex. Below are my test strings, with the highlighted sections being what I want the regex to match.
Particularly, I'm having trouble getting the regex to match the true start of an equation. My current regex gets thrown off if there are numbers or words before the equation starts. I feel like I need to somehow work backwards from the equals sign. I started reversing my string characters around and that's when I threw my hands up and came to you for help.
My test strings with desired matches (the true equation part of the string):
test text (1) pi=
test text (1 pi=
test text 1) pi=
test text (2) pi + 10 / 20=
test text (3) test pi ^ 10 / 20=
test text (30) 10 + 5=
test text (500) abs(10 + 5)=
test text (1) pi + 10 / 20=
test text 10*5=
test text pi / phi=
test text 10 mod phi=
test text 50 10 mod phi=
test text pi mod abs(phi)=
apple banana cherry apple 10 apple cherry banana hi 10 99+1=
Here are all of my special key words allowed and useful in napkin math:
var napkinMathKeyWords = [
'pi',
'\\u03C0',
'\\u03A0',
'phi',
'\\u03C6',
'\\u03A6',
'abs',
'acos',
'cos',
'atan',
'tan',
'asin',
'sin',
'ceil',
'floor',
'sqrt',
'log',
'ln',
'mod',
];
EDIT
Here's the regex I've got so far:
(\d|pi|\\u03C0|\\u03A0|phi|\\u03C6|\\u03A6|abs|acos|cos|atan|tan|asin|sin|ceil|floor|sqrt|log|ln|mod).*?=
It's hitting most of my cases, there are just a couple of cases throwing it off:
http://i.imgur.com/QbueeFC.png
[1] http://blogs.msdn.com/b/onenotetips/archive/2008/05/09/napkin-math-in-onenote.aspx
As you implied, this regex gets a little messy. But I have one that works (see regex101). On regex101, I used the PCRE mode, but only so I could use the "extended" option to make the regex more readable. In JavaScript, just collapse all the line-breaks and spaces and it will work.
I realized that your list of keywords contained two distinct groups:
keywords that are functions, to be followed by operations in parens
var regex_function = "(abs|acos|cos|atan|tan|asin|sin|ceil|floor|sqrt|log|ln)\([^)]+)";
keywords that are constants (stand-alone)
var regex_constant = "(\d+|pi|\\u03C0|\\u03A0|phi|\\u03C6|\\u03A6)";
Then the combination (alternation) of the above parts represents an operand:
var regex_operand = "(" + regex_constant + "|" + regex_function + ")";
Each operand must have an operator in-between:
var regex_operator = "([+\-*\/^]|mod)";
The entire regex can be put together like this:
var regex = new RegExp(regex_operand + "(\s*" + regex_operator + "\s*" + regex_operand + ")*\s*=");
Basically, you have an operand followed by any number of operator/operand pairs, then the equal sign.
Looks to me like your best bet is asserting that spaces must always be followed by some sort of operator . For instance, "5 5 =" is invalid while "5 + 5 =" and "5 =" are valid. Thus, I'd say your regex should look something like this:
([numbers and special names like pi][ ]?[operators][ ]?)*[numbers and special names like pi][ ]?\=[ ]?
I may have written the spaces wrong, what I mean to say is that they can appear at most one time. The other things in brackets would just be big or statements. Parentheses might get tricky, if I get the chance I'll edit my answer to properly handle them.
I'm writing some javascript that processes website content. My efforts are being thwarted by SharePoint text editor's tendency to put the "zero width space" character in the text when the user presses backspace.
The character's unicode value is 8203, or B200 in hexadecimal. I've tried to use the default "replace" function to get rid of it. I've tried many variants, none of them worked:
var a = "om"; //the invisible character is between o and m
var b = a.replace(/\u8203/g,'');
= a.replace(/\uB200/g,'');
= a.replace("\\uB200",'');
and so on and so forth. I've tried quite a few variations on this theme. None of these expressions work (tested in Chrome and Firefox) The only thing that works is typing the actual character in the expression:
var b = a.replace("",''); //it's there, believe me
This poses potential problems. The character is invisible so that line in itself doesn't make sense. I can get around that with comments. But if the code is ever reused, and the file is saved using non-Unicode encoding, (or when it's deployed to SharePoint, there's not guarantee it won't mess up encoding) it will stop working. Is there a way to write this using the unicode notation instead of the character itself?
[My ramblings about the character]
In case you haven't met this character, (and you probably haven't, seeing as it's invisible to the naked eye, unless it broke your code and you discovered it while trying to locate the bug) it's a real a-hole that will cause certain types of pattern matching to malfunction. I've caged the beast for you:
[] <- careful, don't let it escape.
If you want to see it, copy those brackets into a text editor and then iterate your cursor through them. You'll notice you'll need three steps to pass what seems like 2 characters, and your cursor will skip a step in the middle.
The number in a unicode escape should be in hex, and the hex for 8203 is 200B (which is indeed a Unicode zero-width space), so:
var b = a.replace(/\u200B/g,'');
Live Example:
var a = "om"; //the invisible character is between o and m
var b = a.replace(/\u200B/g,'');
console.log("a.length = " + a.length); // 3
console.log("a === 'om'? " + (a === 'om')); // false
console.log("b.length = " + b.length); // 2
console.log("b === 'om'? " + (b === 'om')); // true
The accepted answer didn't work for my case.
But this one did:
text.replace(/(^[\s\u200b]*|[\s\u200b]*$)/g, '')
var shortLocString = locationString;
console.log("Index of dash in '" + shortLocString + "': " + shortLocString.indexOf('-'));
prints this every time:
Index of dash in '325–333 Avenue C, New York, NY': -1
Why do I feel like this is some stupid thing I'm missing at the end of a long day?
Thanks for the help!
Mike
You have some sort of not-hyphen character in your string. I'm not sure which one; there are a bunch that look like that.
There are many hyphen-like characters available.
If you type in "-", it might not be the same as the character which is being put in the string you're testing.
If you have the string you want to test (ie: that one), an easy solution might be to copy the dash which exists inside of the string, paste it into your .indexOf and try again.
For a more-robust solution, get the Unicodes for all hyphens (include the actual minus sign), and if you're dealing with phone-numbers or serial-numbers which have to be formatted the same way, every time, then manually do a RegEx replace of any of those dashes, into the format you will use for your checks.
Also, be prepared for headaches with MS Word or other rich-text editors.
They will swap your " for fancy quotes in a heartbeat, and then all of your strings are broken. They may also use different character-mappings for accents, et cetera.
It's because there's more than one type of dash - you're checking for a hyphen, but the address contains an en dash.
console.log("Index of dash in '" + shortLocString + "': " + shortLocString.indexOf('\u2013'));
should print
Index of dash in '325–333 Avenue C, New York, NY': 3
If your addresses are likely to include em and/or en dashes you'll want to check for the characters \u2013 and \u2014
There are many posts like this and I have found a few solutions but there are not perfect.
One of them:
"aabbhahahahahahahahahahahasetsetset".replace(/[^\w\s]|(.+)\1+/gi, '$1')
The results is:
abhahahahahahaset
I want to get result:
abhaset
How to do this ?
.+ is greedy. It takes as much as it can. That is half of the has so that \1 can match the second half. Making the repetition ungreedy should do the trick:
/[^\w\s]|(.+?)\1+/gi
By the way, the i doesn't change anything here.
To get rid of nested repetitions (e.g. transform aaBBaaBB into aB (via aaBB or aBaB)) simply run the replacement multiple times until the result does not change any more.
var pattern = /[^\w\s]|(.+?)\1+/g;
var output = "aaBBaaBB";
var input;
do
{
input = output;
output = input.replace(pattern, "$1");
} while (input != output)
I admit the naming of output is a bit awkward for the first repetition, but you know... the two most difficult problems in computer science are cache invalidation, naming things and off-by-one errors.
.+ will match the maximum amount possible, so hahahaha satisfies (.+)\1 with haha and haha. You want to match the minimum amount possible, so use a reluctant quantifier.
"aabbhahahahahahahahahahahasetsetset".replace(/[^\w\s]|(.+?)\1+/gi, '$1')
http://jsfiddle.net/HQRDg/
Friends,
I'm new to both Javascript and Regular Expressions and hope you can help!
Within a Javascript function I need to check to see if a comma(,) appears 1 or more times. If it does then there should be one or more numbers either side of it.
e.g.
1,000.00 is ok
1,000,00 is ok
,000.00 is not ok
1,,000.00 is not ok
If these conditions are met I want the comma to be removed so 1,000.00 becomes 1000.00
What I have tried so is:
var x = '1,000.00';
var regex = new RegExp("[0-9]+,[0-9]+", "g");
var y = x.replace(regex,"");
alert(y);
When run the alert shows ".00" Which is not what I was expecting or want!
Thanks in advance for any help provided.
strong text
Edit
strong text
Thanks all for the input so far and the 3 answers given. Unfortunately I don't think I explained my question well enough.
What I am trying to achieve is:
If there is a comma in the text and there are one or more numbers either side of it then remove the comma but leave the rest of the string as is.
If there is a comma in the text and there is not at least one number either side of it then do nothing.
So using my examples from above:
1,000.00 becomes 1000.00
1,000,00 becomes 100000
,000.00 is left as ,000.00
1,,000.00 is left as 1,,000.00
Apologies for the confusion!
Your regex isn't going to be very flexible with higher orders than 1000 and it has a problem with inputs which don't have the comma. More problematically you're also matching and replacing the part of the data you're interested in!
Better to have a regex which matches the forms which are a problem and remove them.
The following matches (in order) commas at the beginning of the input, at the end of the input, preceded by a number of non digits, or followed by a number of non digits.
var y = x.replace(/^,|,$|[^0-9]+,|,[^0-9]+/g,'');
As an aside, all of this is much easier if you happen to be able to do lookbehind but almost every JS implementation doesn't.
Edit based on question update:
Ok, I won't attempt to understand why your rules are as they are, but the regex gets simpler to solve it:
var y = x.replace(/(\d),(\d)/g, '$1$2');
I would use something like the following:
^[0-9]{1,3}(,[0-9]{3})*(\.[0-9]+)$
[0-9]{1,3}: 1 to 3 digits
(,[0-9]{3})*: [Optional] More digit triplets seperated by a comma
(\.[0-9]+): [Optional] Dot + more digits
If this regex matches, you know that your number is valid. Just replace all commas with the empty string afterwards.
It seems to me you have three error conditions
",1000"
"1000,"
"1,,000"
If any one of these is true then you should reject the field, If they are all false then you can strip the commas in the normal way and move on. This can be a simple alternation:
^,|,,|,$
I would just remove anything except digits and the decimal separator ([^0-9.]) and send the output through parseFloat():
var y = parseFloat(x.replace(/[^0-9.]+/g, ""));
// invalid cases:
// - standalone comma at the beginning of the string
// - comma next to another comma
// - standalone comma at the end of the string
var i,
inputs = ['1,000.00', '1,000,00', ',000.00', '1,,000.00'],
invalid_cases = /(^,)|(,,)|(,$)/;
for (i = 0; i < inputs.length; i++) {
if (inputs[i].match(invalid_cases) === null) {
// wipe out everything but decimal and dot
inputs[i] = inputs[i].replace(/[^\d.]+/g, '');
}
}
console.log(inputs); // ["1000.00", "100000", ",000.00", "1,,000.00"]