Estoy tratando de hacer coincidir el encabezado de rebajas usando expresiones regulares en javascript. Un encabezado de descuento es una cadena que comienza con uno o más # seguidos de uno o más espacios y algunos textos más, como este:
## This is the titleLo complicado es que me dan una cadena de varias líneas y una posición de inicio indexada en 0, necesito verificar si la cadena que comienza en la posición dada comienza con un encabezado de descuento. En otras palabras, necesito escribir la siguiente función:
/** * The function should return true in the following situations: * - text: "abc\n# My Title", startPos = 4 * - text: "abc\n# My Title\nxyz", startPos = 4 * * The function should return false in the following situation: * - text "abc\n#My Title", startPos = 0 */ function isMarkdownHeader(text, startPos) { ... }Esto es lo que he probado:
function isMarkdownHeader(text, startPos) { const pattern = new RegExp(`^[^]{${startPos}}(^#+)(\\s+)(.*$)`, 'm'); return pattern.exec(text) != null; } console.log(isMarkdownHeader("abc\n## My Title\nxyz", 4)); // true console.log(isMarkdownHeader("abc\n## My Title\nxyz", 0)); // true, which is incorrect. La función debería devolver false en la segunda invocación. Pero no fue así. ¿Por qué? ¿Cómo puedo hacer que funcione?
Puedes usar
^.{4}(#+\s+.*)Y la función se verá
function isMarkdownHeader(text, startPos) { const pattern = new RegExp(`^.{${startPos}}#+\\s+.*`, "s"); return pattern.exec(text) != null; } isMarkdownHeader("abc\n## My Title\nxyz", 4) // true isMarkdownHeader("abc\n## My Title\nxyz", 0) // false NOTA: Aquí he usado la bandera s . Además, vea la demostración .
Puede dividir la cadena de entrada antes de verificar la validez.
function isMarkdownHeader(text, startPos) { const pattern = /^#+\s+.*/; return !!pattern.exec(text.slice(startPos)); } isMarkdownHeader("abc\n## My Title\nxyz", 4) // true isMarkdownHeader("abc\n## My Title\nxyz", 0) // false
isMarkdownHeader("abcd## My Title\nxyz", 4)debería devolverfalse. Con su código, el valor de retorno estrue
Eso ocurre porque las cosas llamadas nueva línea y el carácter \n no son lo mismo. \n en una cadena es un carácter regular de la nueva línea y se convierte en una nueva línea después de que imprimimos la cadena. Entonces, si desea hacer coincidir ambos, use
^.{4}(?:^|\n|\\n)(#+\s+.*)(?:^|\n|\\n) patrón al anterior(?: grupo que no captura^|\n|\\n Coincide con el inicio de una cadena, una nueva línea o un carácter \n) Cerrar grupo no capturadorabcd\n## My Title\nxyzabcd⏎## My Title\nxyz donde ⏎ es una nueva línea PD Para hacer coincidir abc\n## My Title\nxyz , debe usar 3 como startPos , sin incluir el carácter \n .
function isMarkdownHeader(text, startPos) { const pattern = new RegExp(`^.{${startPos}}(?:^|\\n|\\\\n)(#+\\s+.*)`, "s"); return pattern.exec(text) != null; } console.log(isMarkdownHeader("abc\n## My Title\nxyz", 3)) // true console.log(isMarkdownHeader("abc\n## My Title\nxyz", 0)) // false console.log(isMarkdownHeader("abcd## My Title\nxyz", 4)) // falseSegún Regex101 , el cuantificador {0} hace que se ignore el token anterior. No hay ninguna cita que respalde eso, pero les tomaré la palabra.
Siendo así, puede verificar que su coincidencia comience en el índice 0 (lo que indica que la cadena comenzó con el número correcto de caracteres ignorados).
function isMarkdownHeader(text, startPos) { const pattern = new RegExp(`^[^]{${startPos}}(^#+)(\\s+)(.*$)`, 'm'); const match = pattern.exec(text); return match?.index === 0; } console.log(isMarkdownHeader("abc\n## My Title\nxyz", 4)); // true console.log(isMarkdownHeader("abc\n## My Title\nxyz", 0)); // now falseNo necesita la expresión regular para comenzar en una determinada posición. Simplemente puede pasar la subcadena que comienza en startPos :
return pattern.exec(text.substring(startPos)) != null;