Para extraer asignaciones como title = "Blue = Green", busca la clave y el valor completo entre comillas a la vez. Esta guía para Mac usa JavaScript en Safari para conservar los signos de igual, las comillas y las barras invertidas internas, e informar de las líneas mal formadas.
¿Por qué dividir por los signos de igual hace que se pierda parte del valor?
Considera esta asignación sintética:
title = "Blue = Green"
La clave prevista es title; el valor, incluidas sus comillas originales, es "Blue = Green". Solo el primer signo de igual separa los campos. El segundo forma parte del texto entre comillas.
split("=") de JavaScript divide en cada aparición sin interpretar las comillas. Añadir un límite, como en split("=", 2), trunca la matriz resultante; no conserva todo lo que viene después del primer separador. Esto se ajusta a la definición de String.prototype.split del estándar.
El método adecuado depende de la gramática de la entrada. Usa esta guía para decidir antes de modificar el texto:
| Condición de entrada | Enfoque adecuado |
|---|---|
| Una asignación por línea; solo importa la separación | Localiza el primer signo de igual y conserva todo el resto. |
| Una asignación por línea; también hay que comprobar las comillas y la sintaxis de la clave | Busca la línea completa con un patrón de asignación definido, como el siguiente. |
| Varias asignaciones por línea o valores que ocupan varias líneas | Usa un analizador diseñado para esas reglas adicionales. |
Para esta tarea, validar la línea completa ofrece una comprobación adicional útil: una comilla sin pareja o texto final inesperado genera un error en lugar de una extracción incompleta.
¿Qué gramática de asignación conserva este ejemplo?
El programa siguiente implementa deliberadamente un formato de texto reducido. Estas son las reglas definidas aquí, no una afirmación de que analice todas las asignaciones de JavaScript:
- Cada línea no vacía contiene una asignación.
- Las claves empiezan con una letra ASCII o un guion bajo, seguidos de letras ASCII, dígitos o guiones bajos.
- Los valores usan comillas rectas simples o dobles, con delimitadores coincidentes. Los valores vacíos entre comillas son válidos.
- Dentro de un valor, una barra invertida se empareja con el carácter siguiente, excepto si es un retorno de carro o un salto de línea. Ambos caracteres se conservan sin cambios.
- Puede haber espacios y tabulaciones alrededor de la clave, el separador y el valor. Los espacios y las tabulaciones dentro de las comillas forman parte del valor.
- Los finales de línea físicos pueden ser LF, CRLF o CR. Los valores entre comillas no pueden cruzar esos finales de línea.
- Los comentarios, los puntos y coma y los valores sin comillas quedan fuera de esta gramática.
Por ejemplo, caption='Small = calm' es válido. También lo es note="Use \"a=b\" here": las comillas dobles escapadas forman parte del valor. En cambio, caption='Small = calm" tiene delimitadores que no coinciden y debe corregirse.
El resultado guarda cada valor como rawValue, incluidas las comillas que lo delimitan. La extracción no decodifica las secuencias de escape: los dos caracteres \n siguen siendo dos caracteres. Esto hace que el resultado sirva para reorganizar el texto de las asignaciones sin cambiar su representación escrita.
Las claves duplicadas también permanecen en entradas separadas y en su orden original. Así se evita reemplazar silenciosamente un valor anterior cuando vuelve a aparecer la misma clave.
¿Cómo se ejecuta la transformación en Safari en un Mac?
El inspector web de Safari ofrece un espacio para ejecutar JavaScript. Actívalo en Safari → Configuración… → Avanzado → Mostrar funciones para desarrolladores web. Luego elige Desarrollador → Mostrar inspector web, o pulsa Opción-Comando-I. Estos pasos se documentan en Activar el inspector web de WebKit.
Selecciona la pestaña Consola y usa el campo de entrada para ejecutar el programa completo que aparece a continuación. WebKit documenta ese campo como una entrada para ejecutar JavaScript en su referencia de la interfaz del inspector web. El ejemplo opera únicamente sobre la cadena definida dentro del programa.
El ejemplo usa String.raw para que las barras invertidas se conserven al construir la cadena de JavaScript. Al editar el ejemplo, recuerda que las comillas invertidas y ${...} siguen teniendo significado en las plantillas literales; esta entrada no contiene ninguna de las dos cosas. Consulta la documentación de JavaScript sobre String.raw() antes de añadir esos caracteres.
(() => {
const source = String.raw`title = "Blue = Green"
caption='Small = calm'
note = "Use \"a=b\" here"
marker = "$1 = $$"
empty = ""`;
const assignment = /^[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*=[ \t]*("(?:\\[^\r\n]|[^"\\\r\n])*"|'(?:\\[^\r\n]|[^'\\\r\n])*')[ \t]*$/;
function extractAssignments(text) {
const pairs = [];
const errors = [];
const lines = text.split(/\r\n|\n|\r/);
lines.forEach((line, index) => {
if (/^[ \t]*$/.test(line)) return;
const match = assignment.exec(line);
if (!match || match[0].length !== line.length) {
errors.push(`Line ${index + 1}: expected key = quoted value`);
return;
}
pairs.push({ key: match[1], rawValue: match[2] });
});
if (errors.length) throw new Error(errors.join("\n"));
return pairs;
}
const pairs = extractAssignments(source);
const extracted = pairs
.map(({ key, rawValue }) => `key: ${key}\nvalue: ${rawValue}`)
.join("\n\n");
console.log(extracted);
const normalized = source.split(/\r\n|\n|\r/)
.map(line => line.replace(assignment,
(_whole, key, rawValue) => key + " = " + rawValue))
.join("\n");
console.log("Normalized assignments:\n" + normalized);
})();
Es un programa completo con datos de ejemplo, sin importaciones ni paquetes adicionales. La función contenedora mantiene las declaraciones en el ámbito local, lo que permite volver a ejecutar todo el ejemplo después de editar los datos de muestra.
El primer mensaje de la consola separa los campos:
key: title
value: "Blue = Green"
key: caption
value: 'Small = calm'
key: note
value: "Use \"a=b\" here"
key: marker
value: "$1 = $$"
key: empty
value: ""
El segundo mensaje muestra las asignaciones con un espaciado uniforme:
Normalized assignments:
title = "Blue = Green"
caption = 'Small = calm'
note = "Use \"a=b\" here"
marker = "$1 = $$"
empty = ""
Selecciona y copia el bloque de texto que mejor se adapte a la tarea en el escritorio. El programa muestra los resultados mediante console.log, que WebKit documenta en su API del objeto Console. No escribe ningún archivo.
¿Cómo mantiene el patrón intactos los signos de igual entre comillas?
El patrón tiene dos grupos de captura: uno para la clave y otro para el valor completo entre comillas. Sus grupos internos (?:...) organizan las alternativas sin crear campos capturados adicionales. Este uso de grupos de captura y no captura se ajusta a la documentación sobre grupos de JavaScript.
Después de buscar la clave, el patrón consume una vez el separador de la asignación. Luego elige la rama entre comillas dobles o la rama entre comillas simples. Cada rama acepta caracteres normales, incluidos los signos de igual, o una barra invertida emparejada con el carácter siguiente. Una comilla coincidente sin escape cierra esa rama.
Esta estructura maneja las comillas escapadas sin tratarlas como el final del valor. También maneja las barras invertidas emparejadas: después de consumir juntas un par, una comilla siguiente sin escape puede cerrar la cadena. Los valores vacíos funcionan porque el contenido entre comillas puede repetirse cero veces.
El programa lee las capturas mediante match[1] y match[2]. Una llamada fallida a exec() devuelve null, según lo especificado por ECMAScript en RegExp.prototype.exec. La comparación adicional de longitud exige que la coincidencia abarque toda la línea física.
Solo los espacios y las tabulaciones cuentan como formato circundante. El programa nunca recorta el interior de un valor. Por eso, label = " Blue = Green " conserva los espacios en ambos extremos del contenido entre comillas.
¿Por qué usar una función de reemplazo para reformatear?
El paso de normalización devuelve la clave capturada, un separador estandarizado y el valor capturado. La función de reemplazo recibe primero la coincidencia completa y, a continuación, las dos capturas. JavaScript documenta este orden de argumentos en String.prototype.replace().
El texto que devuelve una función de retorno se inserta literalmente, sin interpretar tokens de reemplazo como $1 o $$. Así, el valor de ejemplo "$1 = $$" permanece intacto. La misma documentación explica esta diferencia entre las cadenas de reemplazo y las funciones de reemplazo.
Una plantilla de reemplazo fija como "$1 = $2" también funcionaría con este patrón concreto: el contenido capturado se inserta sin una segunda pasada de sustitución. La función resulta especialmente útil al construir texto de reemplazo de forma dinámica, porque mantiene el valor devuelto separado de la sintaxis de las plantillas de reemplazo.
La normalización cambia intencionadamente los espacios circundantes y convierte los finales de línea físicos en LF. Conserva las líneas vacías y el texto exacto de los valores entre comillas. Si la tarea requiere los espacios y finales de línea originales, usa los pares extraídos para inspeccionarlos y deja intacto el source original.
¿Qué debes comprobar antes de usar el resultado?
La función de extracción recopila los errores numerados por línea y los genera antes de imprimir cualquiera de los resultados. Las líneas vacías que solo contienen espacios o tabulaciones se ignoran explícitamente. Así, una línea mal formada no puede desaparecer en un resultado parcial que parezca correcto.
Usa estos casos sintéticos para diagnosticar entradas inesperadas:
| Texto de asignación | Resultado esperado |
|---|---|
x="a=b=c" |
Conserva todo el valor entre comillas. |
x='' |
Acepta un valor vacío entre comillas simples. |
x=" a=b " |
Conserva los espacios dentro de las comillas. |
x="a\"=b" |
Conserva la comilla escapada y el signo de igual. |
x="a=b |
Informa de que falta la comilla de cierre. |
x="a" extra |
Informa de que sobra texto al final. |
x="a" y="b" |
Rechaza varias asignaciones en una sola línea. |
x=a=b |
Rechaza un valor sin comillas según esta gramática. |
La lógica de extracción y normalización del programa se ejecutó en Node.js 20.19.2 con el ejemplo mostrado. Otras quince comprobaciones deterministas cubrieron signos de igual entre comillas, valores vacíos, comillas escapadas, barras invertidas emparejadas, tokens de dólar literales, líneas mal formadas, claves duplicadas y el tratamiento de líneas vacías. Esto verifica la lógica de transformación definida; no significa que se haya probado la interfaz de Safari.
Si una línea falla, comprueba primero sus delimitadores y luego busca una barra invertida final sin pareja, texto sobrante o una clave no admitida. Modifica la gramática de forma deliberada cuando la tarea requiera más sintaxis. Para el formato indicado, con una asignación por línea, el resultado es un par de campos reutilizable cuyo valor entre comillas conserva todos los signos de igual internos.
Fuentes
- Activar el inspector web — WebKit.
- Interfaz del inspector web — WebKit.
- API del objeto Console — WebKit.
- Especificación del lenguaje ECMAScript® 2027 — Procesamiento de texto — Ecma International / TC39, borrador en evolución.
- String.raw() — MDN Web Docs.
- Grupos y referencias inversas — MDN Web Docs.
- String.prototype.replace() — MDN Web Docs.