Para extrair atribuições como title = "Blue = Green", capture juntos a chave e o valor completo entre aspas. Este guia para Mac usa JavaScript no Safari para preservar sinais de igual, aspas e barras invertidas internas, além de indicar linhas malformadas.
Por que dividir nos sinais de igual faz o valor se perder?
Considere esta atribuição sintética:
title = "Blue = Green"
A chave pretendida é title; o valor, incluindo as aspas originais, é "Blue = Green". Apenas o primeiro sinal de igual separa os campos. O segundo pertence ao texto entre aspas.
O split("=") do JavaScript divide em cada ocorrência sem interpretar aspas. Adicionar um limite, como em split("=", 2), trunca o array resultante; isso não preserva tudo o que vem depois do primeiro separador. Isso segue a definição de String.prototype.split da especificação.
O método adequado depende da gramática da entrada. Use este guia de decisão antes de alterar o texto:
| Condição da entrada | Abordagem adequada |
|---|---|
| Uma atribuição por linha; só importa separar | Localize o primeiro sinal de igual e mantenha todo o restante. |
| Uma atribuição por linha; as aspas e a sintaxe da chave também precisam ser verificadas | Combine a linha inteira com um padrão de atribuição definido, como abaixo. |
| Várias atribuições por linha ou valores que ocupam várias linhas | Use um analisador projetado para essas regras adicionais. |
Para esta tarefa, validar a linha inteira oferece uma verificação extra útil: uma aspa sem par ou texto final inesperado gera um erro em vez de uma extração incompleta.
Qual gramática de atribuição este exemplo preserva?
O programa abaixo implementa um formato de texto deliberadamente simples. Estas são as regras definidas para ele, não uma afirmação de que analisa todas as atribuições de JavaScript:
- Cada linha não vazia contém uma atribuição.
- As chaves começam com uma letra ASCII ou sublinhado, seguidos de letras ASCII, dígitos ou sublinhados.
- Os valores usam aspas retas correspondentes, simples ou duplas. Valores vazios entre aspas são válidos.
- Dentro de um valor, uma barra invertida forma um par com o caractere seguinte, exceto se este for um retorno de carro ou uma quebra de linha. Ambos os caracteres permanecem inalterados.
- Espaços e tabulações podem aparecer ao redor da chave, do separador e do valor. Espaços e tabulações dentro das aspas fazem parte do valor.
- As terminações físicas de linha podem ser LF, CRLF ou CR. Os valores entre aspas não podem atravessar essas terminações.
- Comentários, ponto e vírgula e valores sem aspas não fazem parte desta gramática.
Por exemplo, caption='Small = calm' é válido. note="Use \"a=b\" here" também: as aspas duplas escapadas pertencem ao valor. Em contrapartida, caption='Small = calm" tem delimitadores incompatíveis e precisa ser corrigido.
A saída armazena cada valor como rawValue, incluindo as aspas que o envolvem. A extração não decodifica sequências de escape: os dois caracteres \n continuam sendo dois caracteres. Isso torna o resultado adequado para reorganizar o texto das atribuições sem alterar sua representação escrita.
Chaves duplicadas também permanecem em entradas separadas, na ordem original. Essa escolha evita substituir silenciosamente um valor anterior quando a mesma chave aparece novamente.
Como executar a transformação no Safari em um Mac?
O Inspetor Web do Safari oferece um local para avaliar JavaScript. Ative-o em Safari → Ajustes… → Avançado → Mostrar recursos para desenvolvedores web. Em seguida, escolha Desenvolvedor → Mostrar Inspetor Web ou pressione Option-Command-I. Essas etapas estão documentadas em Como ativar o Inspetor Web, da WebKit.
Selecione a aba Console e use o campo de entrada para inserir o programa completo abaixo. A WebKit documenta esse campo como uma área de entrada para avaliar JavaScript na referência da interface do Inspetor Web. O exemplo opera apenas sobre a string definida no próprio programa.
O exemplo usa String.raw para que as barras invertidas sobrevivam à construção da string JavaScript. Ao editar o exemplo, lembre-se de que crases e ${...} ainda têm significado em literais de modelo; esta entrada não contém nenhum dos dois. Consulte a documentação de String.raw() do JavaScript antes de adicionar esses 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);
})();
Este é um programa completo com dados de exemplo, sem importações nem pacotes adicionais. A função que o envolve mantém as declarações locais, permitindo executar o exemplo inteiro novamente após editar os dados de amostra.
A primeira mensagem do console separa os 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: ""
A segunda mensagem apresenta as atribuições com espaçamento uniforme:
Normalized assignments:
title = "Blue = Green"
caption = 'Small = calm'
note = "Use \"a=b\" here"
marker = "$1 = $$"
empty = ""
Selecione e copie o bloco de texto que for adequado à tarefa no computador. O programa exibe os resultados por meio de console.log, documentado pela WebKit na API do objeto Console. Ele não grava um arquivo.
Como o padrão mantém intactos os sinais de igual entre aspas?
O padrão tem dois grupos de captura: um para a chave e outro para o valor completo entre aspas. Seus grupos internos (?:...) organizam alternativas sem criar campos capturados adicionais. Esse uso de grupos de captura e não captura segue a documentação de grupos do JavaScript.
Depois de combinar a chave, o padrão consome uma vez o separador da atribuição. Em seguida, escolhe entre o ramo de aspas duplas e o de aspas simples. Cada ramo aceita caracteres comuns — inclusive sinais de igual — ou uma barra invertida seguida de outro caractere. Uma aspa correspondente sem escape fecha o ramo.
Essa estrutura lida com aspas escapadas sem tratá-las como o fim do valor. Também lida com barras invertidas em pares: depois que um par é consumido em conjunto, uma aspa seguinte sem escape pode fechar a string. Valores vazios funcionam porque o conteúdo entre aspas pode se repetir zero vezes.
O programa lê as capturas por meio de match[1] e match[2]. Uma chamada de exec() sem correspondência retorna null, conforme especificado por RegExp.prototype.exec no ECMAScript. A comparação adicional de comprimento exige que a correspondência cubra a linha física inteira.
Somente espaços e tabulações contam como formatação ao redor. O programa nunca remove espaços de dentro de um valor. Assim, label = " Blue = Green " preserva os espaços nas duas extremidades do conteúdo entre aspas.
Por que usar uma função de substituição ao reformatar?
A etapa de normalização retorna a chave capturada, um separador padronizado e o valor capturado. A função de retorno recebe primeiro a correspondência completa, seguida pelas duas capturas. O JavaScript documenta essa ordem de argumentos em String.prototype.replace().
O texto retornado por uma função de retorno é inserido literalmente, sem interpretar tokens de substituição como $1 ou $$. Isso mantém intacto o valor de exemplo "$1 = $$". A mesma documentação explica essa diferença entre strings de substituição e funções de substituição.
Um modelo de substituição fixo, como "$1 = $2", também funcionaria para este padrão específico: o conteúdo capturado é inserido sem uma segunda passagem de substituição. A função de retorno é especialmente útil ao montar texto de substituição dinamicamente, pois mantém o valor retornado separado da sintaxe do modelo de substituição.
A normalização altera intencionalmente o espaçamento ao redor e converte as terminações físicas de linha para LF. Ela preserva as linhas em branco e o texto exato dos valores entre aspas. Se a tarefa exigir o espaçamento e as terminações de linha originais, use os pares extraídos para inspeção e mantenha o source original inalterado.
O que verificar antes de usar o resultado?
A função de extração reúne erros numerados por linha e os lança antes que qualquer resultado seja impresso. Linhas em branco que contêm apenas espaços ou tabulações são ignoradas explicitamente. Assim, uma linha malformada não pode desaparecer em um resultado parcial aparentemente bem-sucedido.
Use estes casos sintéticos para diagnosticar entradas inesperadas:
| Texto da atribuição | Resultado esperado |
|---|---|
x="a=b=c" |
Preservar todo o valor entre aspas. |
x='' |
Aceitar um valor vazio entre aspas simples. |
x=" a=b " |
Preservar os espaços dentro das aspas. |
x="a\"=b" |
Preservar a aspa escapada e o sinal de igual. |
x="a=b |
Indicar a aspa de fechamento ausente. |
x="a" extra |
Indicar texto final excedente. |
x="a" y="b" |
Rejeitar várias atribuições na mesma linha. |
x=a=b |
Rejeitar um valor sem aspas segundo esta gramática. |
A lógica de extração e normalização do programa foi executada no Node.js 20.19.2 com o exemplo mostrado. Quinze verificações determinísticas adicionais cobriram sinais de igual entre aspas, valores vazios, aspas escapadas, barras invertidas em pares, tokens de dólar literais, linhas malformadas, chaves duplicadas e tratamento de linhas em branco. Isso verifica a lógica de transformação definida; não significa que a interface do Safari tenha sido testada.
Se uma linha falhar, verifique primeiro os delimitadores e depois procure uma barra invertida final sem par, texto excedente ou uma chave não compatível. Altere a gramática deliberadamente quando a tarefa exigir mais sintaxe. Para o formato especificado de uma atribuição por linha, o resultado é um par reutilizável de campos cuja chave preserva todos os sinais de igual internos.
Fontes
- Como ativar o Inspetor Web — WebKit.
- Interface do Inspetor Web — WebKit.
- API do objeto Console — WebKit.
- Especificação da linguagem ECMAScript® 2027 — Processamento de texto — Ecma International / TC39, rascunho em evolução.
- String.raw() — MDN Web Docs.
- Grupos e referências retroativas — MDN Web Docs.
- String.prototype.replace() — MDN Web Docs.