Changing single quotes to double quotes with regular expressions - javascript

I am trying to change all single quotes to double quotes in a string (unless the single quote occurs in the middle of a word). Yet my code doesn't work correctly on an example string:
let r = /(\W)'|'(\W)|^'|'$/g;
let s = "'ble' 'bla' aren't"
s.replace(r, "$1\"$2");
What the code returns is:
""ble" 'bla" aren't"
so the opening quote of 'bla" is a single quote. I don't know why that is. Any ideas as to why my solution doesn't work?

Your solution doesn't work because of overlapping. In e' 'b, '(\W) matches '(quote + space), the space is consumed then the following quote (just before b cannot be match because there is no non-word before it.
Replace the single quote only when preceeded or followed by a non-wordboundary:
let r = /\B'|'\B/g;
let s = "'ble' 'bla' aren't"
s = s.replace(r, "\"");
console.log(s);

Since regex is not very flexible, you can try replace multiple times, I can do that by replace 2 times
let r = /([^a-z])'(\w)/g;
let s = "'ble' 'bla' aren't"
s = s.replace(r, "$1\"$2");
s.replace(/(\w)'([^a-z])/g,"$1\"$2");

The proper use of straight double " and single ' quotes do not belong in properly punctuated text -- they are actually used in code. Curly double “ ” and single ‘ ’ quotes (a.k.a. smart quotes) should be used instead. Just going by context provided by example in OP having the need to keep apostrophe means that the text is content and not code:
How is: "'ble' 'bla' aren't"
going to be: ""ble" "bla" aren't" without conflict?
The double quotes within need to be escaped or outer quotes replaced by backticks if the line is within code. If it's just continent then it's probably grammatically incorrect (don't know for sure)?
The following demo will replace straight double and single quotes with their curly/smart counterparts. It replaces a straight single quote with a curly/smart right single quote ’ when its not preceded by a space, ^, |, [, -,—,/,(,\,[,{,", or ] which is a predicate for a closing quote or an apostrophe.
You can remove the statements that you don't need.
let str = document.querySelector('main').innerHTML;
document.querySelector('output').innerHTML = smarten(str);
function smarten(str) {
// Opening single quote
str = str.replace(/(^|[-—/(\[{"\s])'/g, "$1\u2018");
// Closing single quote and apostrophe
str = str.replace(/'/g, "\u2019");
// Opening double quote
str = str.replace(/(^|[-—/(\[{‘\s])"/g, "$1\u201c");
// Closing double quote
str = str.replace(/"/g, "\u201d");
return str;
}
<main>
<p>From Sun Tzu's <i>The Art of War</i>, "If you know both yourself and your enemy, you can win numerous (literally, 'a hundred') battles without jeopardy."</p>
</main>
<output></output>

Related

How to replace single backslash with double backslash in Javascript

I have seen a lot of duplicates but none of them works
I spend a day to get this thing up. Gone through all duplicates
I need to replace a single backslash with a double backslash.
I am able to replace all other characters with a double backslash.
console.log("hello & 100\|".replace(/([&%$#_{}])/g, "\\"));
I know that two backslashes is indeed used to make a single backslash.
I tried all the possible ways of using regex as well. But neither works.
Here is another snippet I am using.
var replaceableString = "A\B";
replaceableString = replaceableString.replace(/\\/g, "\\\\");
console.log(replaceableString);
Unfortunately, this also is not working.
Please share if there are any workarounds.
var str = "AAA\\BBB\\CCC\\DDD\\EEE";
var rgx = /\\/g;
var res = str.replace(rgx, "\\\\");
console.log(res);
Comments below questions are very revealing. Single backslash \ is escape character. To obtain single backslash we must use double backslashes. So we must use four backslashes(in reality double) for replace the backslash.

Regular expression in JavaScript that matches ${}

I want regular expressions to match string that starts with either ${ , "${ , '${ and ends with } , }' , }". My string may be ${anythinghere}, "${anythinghere}", '${anythinghere}'. I tried with the following
var str = "${a}";
var patt = /^("|'|${)*(}|'|")$/;
var res = patt.test(str);
alert(res);
But my above code always returns false.
You have to escape the inner $ with a backslash, since it's a special character. But that alone won't fix the problem. As it is above, patt matches any string that begins with " or ' or ${, 0 or more times, and ends with } or ' or ". The regular expression that you want would be something like this:
var str = "${a}";
var patt = /^(['"]?)\${.*}\1$/;
var res = patt.test(str);
alert(res);
Here is what each part of patt is doing:
^(['"]?): The string must begin with 0 or 1 single quote, or with 0 or 1 double quote. This is in parentheses so that we can reference it at the end of the regexp
\${: Next must be a dollar sign followed by an open curly bracket
.*: Next must be 0 or more of any character (other than a newline)
}: Next must be a closed curly bracket
\1$: Finally, the string must end with whatever pattern was matched at the beginning of the string. \1 is a "back-reference" to the first capturing group (in the parentheses), so if the string began with a single quote, it will only match if it also ends with a single quote. Same goes for double quotes, and no quotes at all
$ has a special meaning in regex, so it must be escaped using a backslash \. If you want 1 or more wildcards, that's represented with a .+, not a *. The following code will match the test pattern:
/^'?"?\${.+}'?"?$/
You can use
var a=new RegExp("\^(\'\\$\{)[a-z]+(\}\')|(\"\\$\{)[a-z]+(\}\")|(\\$\{)[a-z]+(\})\$");
a.test("${vijay}")//true
a.test("\'${vijay}\'")//true
a.test("\"${vijay}\"")//true
a.test("\'${vijay}\"")//false
If you use only \$ it takes as end og expresion.So use\\$ means $ as a special character
This works:
var str = "\"${a}\"";
var patt = /^\"\$\{((?!\").)+\}\"$/;
var res = patt.test(str);
alert(res);
Note that the value assigned to str has been changed to \"${a}\" in order to reflect what you stated targets. You must escape (put a backslash before) any character you wish to be read literally and not as a metacharacter. In order to have this match any one of your targets at once, simply repeat the pattern in patt three times, separated by pipes as usual, replacing the \" with \' or nothing at all (in which case, you should change the \" inside the inner most parenthesis to }). These changes are shown below:
var patt = /^\"\$\{((?!\").)+\}\"$|^\'\$\{((?!\').)+\}\'$|^\$\{((?!\}).)+\}$/;

Split string on spaces except for in quotes, but include incomplete quotes

I am trying to split a string in JS on spaces except when the space is in a quote. However, an incomplete quote should be maintained. I'm not skilled in regex wizardry, and have been using the below regex:
var list = text.match(/[^\s"]+|"([^"]*)"/g)
However, if I provide input like sdfj "sdfjjk this will become ["sdfj","sdfjjk"] rather than ["sdfj",""sdfjjk"].
You can use
var re = /"([^"]*)"|\S+/g;
By using \S (=[^\s]) we just drop the " from the negated character class.
By placing the "([^"]*)" pattern before \S+, we make sure substrings in quotes are not torn if they come before. This should work if the string contains well-paired quoted substrings and the last is unpaired.
Demo:
var re = /"([^"]*)"|\S+/g;
var str = 'sdfj "sdfjjk';
document.body.innerHTML = JSON.stringify(str.match(re));
Note that to get the captured texts in-between quotes, you will need to use RegExp#exec in a loop (as String#match "drops" submatches).
UPDATE
No idea what downvoter thought when downvoting, but let me guess. The quotes are usually used around word characters. If there is a "wild" quote, it is still a quote right before/after a word.
So, we can utilize word boundaries like this:
"\b[^"]*\b"|\S+
See regex demo.
Here, "\b[^"]*\b" matches a " that is followed by a word character, then matches zero or more characters other than " and then is followed with a " that is preceded with a word character.
Moving further in this direction, we can make it as far as:
\B"\b[^"\n]*\b"\B|\S+
With \B" we require that " should be preceded with a non-word character, and "\B should be followed with a non-word character.
See another regex demo
A lot depends on what specific issue you have with your specific input!
Try the following:
text.match(/".*?"|[^\s]+/g).map(s => s.replace(/^"(.*)"$/, "$1"))
This repeatedly finds either properly quoted substrings (first), OR other sequences of non-whitespace. The map part is to remove the quotes around the quoted substrings.
> text = 'abc "def ghi" lmn "opq'
< ["abc", "def ghi", "lmn", ""opq"]

RegExp for BBCode tags javascript

I have this RegExp, and i dont know what's wrong with it
tag = new RegExp('(\\['+tag+'=("|'|)(.*?)\1\\])((?:.|\\r?\\n)*?)\\[/'+tag+']','g');
The bbcode tags can have double quotation marks, single quotation marks or no quotation marks.
[tag="teste"]123[/tag]
[tag='teste']123[/tag]
[tag=teste]123[/tag]
Desired output in captures: teste and 123
To match the optional quotation marks, it should be ("|'|), (["|\']*) or ("|\'?)?
Whats wrong with the string
First, let's correct the syntax in your string
You need to define the var tag
tag = 'tag';
result = new RegExp( <...> );
You have unballanced quotes in '("|'|) <...> ', that needs to be escaped as ("|\'|)
Also, escape \1 as \\1
so now we have the expression '(\\['+tag+'=("|\'|)(.*?)\\1\\])((?:.|\\r?\\n)*?)\\[/'+tag+']' with the value:
(\[tag=("|'|)(.*?)\1\])((?:.|\r?\n)*?)\[/tag]
What's wrong with the RegEx
Only one thing really, in ("|\'|)(.*?)\\1 you're using \1 to match the same quotation mark as the one used as opening. However, the 1 refers to the first capturing group (the first parenthesis from left to right), but ("|'|) is actually the second set of parenthesis, the second group. All you need to do is change it to \2.
(\[tag=("|'|)(.*?)\2\])((?:.|\r?\n)*?)\[/tag]
That's it!
Let's add some final suggestions
Instead of .*? I would use [^\]]+ (any characters except "]")
Use the i modifier (case-insensitive match, for "[tag]...[/TaG]")
("|'|) is the same as ("|'?)
Instead of (?:.|\r?\n)*? I would use [\s\S]*? as #nhahtdh suggested
Code:
tag = 'tag';
result = new RegExp('(\\['+tag+'=("|\'?)([^\\]]+)\\2\\])([\\s\\S]*?)\\[/'+tag+']','gi');
Alternative: [EDIT: from info added in comments]
result = new RegExp('\\['+tag+'(?:=("|\'?)([^\\]]+)\\1)?\\]([\\s\\S]*?)\\[/'+tag+']', 'gi');
As for your second question: Although both (["|\']*) and ("|\'?) will match, the latter is the correct way for what you're trying to match. The * looks for 0 to infinite repetitions, and the | is interpreted as literal in a character class. Instead, ("|\'?) matches a single quote, a double quote, or none.

javascript replace all occurrences ",\S" with ", \S"

I want to have spaces separating items in a CSV string. That is "123,456,789" => "123, 456, 789". I have tried, but been unable to construct a regexp to do this. I read some postings and thought this would to the trick, but no dice.
text = text.replace(new RegExp(",\S", "g"), ", ");
Could anyone show me what I am doing wrong?
You have two problems:
Backslashes are a pain in the, um, backslash; because they have so many meanings (e.g. to let you put a quote-mark inside a string), you often end up needing to escape the backslash with another backslash, so you need ",\\S" instead of just ",\S".
The \S matches a character other than whitespace, so that character gets removed and replaced along with the comma. The easiest way to deal with that is to "capture" it (by putting it in parentheses), and put it back in again in the replacement (with $1).
So what you end up with is this:
text = text.replace(new RegExp(',(\\S)', "g"), ", $1");
However, there is a slightly neater way of writing this, because JavaScript lets you write a regex without having a string, by putting it between slashes. Conveniently, this doesn't need the backslash to be escaped, so this much shorter version works just as well:
text = text.replace(/,(\S)/g, ", $1");
As an alternative to capturing, you can use a "zero-width lookahead", which in this situation basically means "this bit has to be in the string, but don't count it as part of the match I'm replacing". To do that, you use (?=something); in this case, it's the \S that you want to "look ahead to", so it would be (?=\S), giving us this version:
text = text.replace(/,(?=\S)/g, ", ");
There are 2 mistakes in your code:
\S in a string literal translates to just S, because \S is not a valid escape sequence. As such, your regex becomes /,S/g, which doesn't match anything in your example. You can escape the backslash (",\\S") or use a regex literal (/,\S/g).
After this correction, you will replace the character following the comma with a space. For instance, 123,456,789 becomes 123, 56, 89. There are two ways to fix this:
Capture the non-space character and use it in the replacement expression:
text = text.replace(/,(\S)/g, ', $1')
Use a negative lookahead assertion (note: this also matches a comma at the end of the string):
text = text.replace(/,(?!\s)/g, ', ')
text = text.replace(/,(\S)/g, ', $1');
try this:
var x = "123,456,789";
x = x.replace(new RegExp (",", "gi"), ", ");

Categories

Resources