Getting the contents in quotes
If you have exactly one sentence per line, you don’t need regex. Just use split
to separate lines and then see if each line starts and ends with quotes:
const texto = `"Deve selecionar as aspas de abertura e fechamento"
'Deve selecionar as aspas de abertura e fechamento'
"Deve ignorar essa ocorrência interna 'de aspas simples' e selecionar somente as de abertura e fechamento da string"
"Deve ignorar essa ocorrência escapada \\"de aspas duplas\\" e selecionar somente as de abertura e fechamento da string"
"Aspas de abertura diferente do fechamento'
Essa string não tem aspas de abertura e fechamento, então deve ser ignorada
Essa string tem aspas aqui ', porém, como não é no inicio e no fim, deve ser ignorada`;
for (const linha of texto.split('\n')) {
let primeiro = linha[0]; // primeiro caractere da linha
let ultimo = linha.slice(-1); // último caractere da linha
// se começa com aspas e termina com a mesma aspas
if ((primeiro === '"' || primeiro === "'") && primeiro === ultimo) {
// pega o texto entre as aspas
console.log(linha.slice(1, -1));
}
}
If the string has Windows line breaks (\r\n
), you can switch to texto.split(/[\r\n]+/)
(so, he considers one or more \r
or \n
in sequence).
Of course it can also be done with regex. Yours didn’t work because it only checks if it starts with quotes or ends with quotation marks (only one of these conditions is sufficient). Also, it does not guarantee that the opening quotes are the same as the closure (it could start with "
and end with '
or vice versa).
With regex would look like this:
const texto = `"Deve selecionar as aspas de abertura e fechamento"
'Deve selecionar as aspas de abertura e fechamento'
"Deve ignorar essa ocorrência interna 'de aspas simples' e selecionar somente as de abertura e fechamento da string"
"Deve ignorar essa ocorrência escapada \\"de aspas duplas\\" e selecionar somente as de abertura e fechamento da string"
"Aspas de abertura diferente do fechamento'
Essa string não tem aspas de abertura e fechamento, então deve ser ignorada
Essa string tem aspas aqui ', porém, como não é no inicio e no fim, deve ser ignorada`;
let r = /^(["'])(.+)\1$/gm;
for (const match of texto.matchAll(r)) {
console.log(match[2]); // pega somente o texto entre as aspas
}
First I put the opening quotes in parentheses, forming a catch group (and since it is the first pair of parentheses of the expression, then it is the first group). At the end I use the back-Ference \1
, which means "the same that was captured in group 1", so I guarantee that the opening and closing quotes should be the same.
I also use the markers ^
and $
, which indicate the beginning and end of the string, but thanks to flag m
, they also indicate the beginning and end of a line. So I guarantee that the quotes should be at the beginning and end of the line.
In between I put .+
, indicating "one or more characters", and within parentheses to form another capture group (in this case, group 2).
I also use the flag g
to take all occurrences and within the for
i print the contents of group 2 (which is the text in the quotes). If you want all the text, including the quotes, use match[0]
.
matchAll
may not work in older browsers, so an alternative is to use exec
:
const texto = `"Deve selecionar as aspas de abertura e fechamento"
'Deve selecionar as aspas de abertura e fechamento'
"Deve ignorar essa ocorrência interna 'de aspas simples' e selecionar somente as de abertura e fechamento da string"
"Deve ignorar essa ocorrência escapada \\"de aspas duplas\\" e selecionar somente as de abertura e fechamento da string"
"Aspas de abertura diferente do fechamento'
Essa string não tem aspas de abertura e fechamento, então deve ser ignorada
Essa string tem aspas aqui ', porém, como não é no inicio e no fim, deve ser ignorada`;
let r = /^(["'])(.+)\1$/gm;
let match;
while (match = r.exec(texto)) {
console.log(match[2]); // pega somente o texto entre as aspas
}
But if nay for one sentence per line, then it gets a little more complicated:
const texto = `"Deve selecionar as aspas de abertura e fechamento" blablabla 'Deve selecionar as aspas de abertura e fechamento' lorem ipsum "Deve ignorar essa ocorrência interna 'de aspas simples' e selecionar somente as de abertura e fechamento da string" fdsafadsf asd "Deve ignorar essa ocorrência escapada \\"de aspas duplas\\" e selecionar somente as de abertura e fechamento da string" fdasfasdfdsa Essa string não tem aspas de abertura e fechamento, então deve ser ignorada
Essa string tem aspas aqui ', porém, como não é no inicio e no fim, deve ser ignorada`;
let r = /"((?:[^"\\]|\\.)+)"|'((?:[^'\\]|\\.)+)'/g;
for (const match of texto.matchAll(r)) {
if (match[0][0] === '"') {
console.log(match[1]); // pega somente o texto entre as aspas
} else {
console.log(match[2]);
}
}
The idea is to pick up the quotes, and in the middle I can have [^"\\]|\\.
:
[^"\\]
: a character that is neither quotation marks nor \
, or
\\.
: one \
followed by any character (so he picks up the escapes)
I do the same for single quotes. The contents between the quotes will be in group 1 or 2, depending on which quotes are taken.
This case only does not detect when it has different opening and closing quotes in the middle of the text (for example, bla "abc' xyz
), because then it becomes impossible to detect whether the different quotation marks are part of the same sentence or not, and will have many false positives (one of them can be considered the opening or closing of other quotation marks that appear before or after, and there would have to be some other criterion to separate the sentences).
Removing the quotation marks
Now if the idea is to remove the quotes, just make a few modifications.
With split
:
const texto = `"Deve selecionar as aspas de abertura e fechamento"
'Deve selecionar as aspas de abertura e fechamento'
"Deve ignorar essa ocorrência interna 'de aspas simples' e selecionar somente as de abertura e fechamento da string"
"Deve ignorar essa ocorrência escapada \\"de aspas duplas\\" e selecionar somente as de abertura e fechamento da string"
"Aspas de abertura diferente do fechamento'
Essa string não tem aspas de abertura e fechamento, então deve ser ignorada
Essa string tem aspas aqui ', porém, como não é no inicio e no fim, deve ser ignorada`;
let novoTexto = '';
for (const linha of texto.split(/(\n)/)) {
let primeiro = linha[0]; // primeiro caractere da linha
let ultimo = linha.slice(-1); // último caractere da linha
// se começa com aspas e termina com a mesma aspas
if ((primeiro === '"' || primeiro === "'") && primeiro === ultimo) {
// pega o texto entre as aspas
novoTexto += linha.slice(1, -1);
} else novoTexto += linha;
}
console.log(novoTexto);
I do the split
using (\n)
(because when there is a capture group in regex, line breaks are included in the result). So I can concatenate the line breaks of the original string.
And with regex:
const texto = `"Deve selecionar as aspas de abertura e fechamento"
'Deve selecionar as aspas de abertura e fechamento'
"Deve ignorar essa ocorrência interna 'de aspas simples' e selecionar somente as de abertura e fechamento da string"
"Deve ignorar essa ocorrência escapada \\"de aspas duplas\\" e selecionar somente as de abertura e fechamento da string"
"Aspas de abertura diferente do fechamento'
Essa string não tem aspas de abertura e fechamento, então deve ser ignorada
Essa string tem aspas aqui ', porém, como não é no inicio e no fim, deve ser ignorada`;
let novoTexto = texto.replace(/^(["'])(.+)\1$/gm, '$2');
console.log(novoTexto);
In the replace
i use $2
, which corresponds to the second catch group (which in this case is the content between the quotation marks).
In case you don’t have a sentence on each line:
const texto = `"Deve selecionar as aspas de abertura e fechamento" blablabla 'Deve selecionar as aspas de abertura e fechamento' lorem ipsum "Deve ignorar essa ocorrência interna 'de aspas simples' e selecionar somente as de abertura e fechamento da string" fdsafadsf asd "Deve ignorar essa ocorrência escapada \\"de aspas duplas\\" e selecionar somente as de abertura e fechamento da string" fdasfasdfdsa Essa string não tem aspas de abertura e fechamento, então deve ser ignorada
Essa string tem aspas aqui ', porém, como não é no inicio e no fim, deve ser ignorada`;
let novoTexto = texto.replace(/"((?:[^"\\]|\\.)+)"|'((?:[^'\\]|\\.)+)'/g, '$1$2');
console.log(novoTexto);
Since the contents in quotes can be in group 1 or 2, I use $1$2
(the group that does not occur will be empty, so it works).
if the string always has that format, you can remove the first and last characters from the string, using
substring
and you don’t even need a regex– Ricardo Pontual
I supplemented the post to be more complete. Not all strings have opening and closing quotes.
– Fábio Jânio
How is this string passed to the program? Is each line an element in an array or is everything just text? I ask because depending on the structure the answer is different.
– Augusto Vasques
It is passed as a single string. The function that does this parse/treat receives a literal string every time it is called.
– Fábio Jânio