#javascript #jquery #regex
#javascript #jquery #регулярное выражение
Вопрос:
Мне нужно добавить круглые скобки или «<>» вокруг каждого совпадения в регулярном выражении, у меня уже готовы все предложения регулярных выражений. Например:
Ввод:
int a = 0;
Вывод:
<int><a><=><0>
Есть еще одна вещь, которую я делаю, это «переводчик», он должен считывать арифметическое число в C и генерировать поток токенов. Так, например, «=» будет <assign_op>
и «;» будет <end_of_statement>
.
Приведенное выше предложение будет записано как:
<int><a><assign_op><0>
Вот код, над которым я работал:
function translate() {
var input = 'int a = 0;'
'nint b = 5;'
'nint a = b 5;'
'nint c = a1 / 1;'
'ndouble a = 1;'
'nfloat a = 0;'
'na = 0;'
'nfloat a = b 1;'
'na = (b - c) * 5;';
var regex3 = new RegExp(/(((int|long int|double|long double|float) s*([a-zA-Z_] d*)*|([a-zA-Z_] d*))s*=s*(([a-zA-Z_]*|[a-zA-Z_] d*)*|d*|d .d );)|(((int|long int|double|long double|float) s*([a-zA-Z_] d*)*|([a-zA-Z_] d*))s*=(s*(*(([a-zA-Z_]*|[a-zA-Z_] d*)*|d*|d .d ))*s*[ -/*%]s*(*(([a-zA-Z_]*|[a-zA-Z_] d*)*|d*|d .d ))*)*s*;)/g);
var text = input.match(regex3);
var varTypes = ['int', 'double', 'float', 'long int', 'long double'];
var output = '';
text.forEach(line => {
varTypes.forEach(type => {
if (line.match(type))
line = line.replace(type, '<' type '>');
});
if (line.match(/=/g)) {
line = line.replace(/=/g, '<assign_op>')
}
if (line.match(/;/g)) {
line = line.replace(/;/g, '<end_of_statement>');
}
if (line.match(/(/g)) {
line = line.replace(/(/g, '<open_parenthesis>')
}
if (line.match(/)/g)) {
line = line.replace(/)/g, '<close_parenthesis>')
}
if (line.match(/[ -*/%]/g)) {
line = line.replace(/[ -*/%]/g, '<operator>')
}
if (line.match(/ {2}/g)) {
line = line.replace(/ {2}/g, '<operator>')
}
output = line 'n';
});
console.log(output);
}
О, извините, если у меня было много ошибок в написании на английском, а не носитель английского языка 🙂
Комментарии:
1. Мне нравится регулярное выражение, но когда оно становится слишком сложным и нечитаемым, возможно, пришло время попробовать другой подход. Поскольку каждый фрагмент во входной переменной структурирован более или менее одинаково, возможно, попробуйте использовать substring для разделения строк на левую и правую части. Все справа, кроме точки с запятой, можно заключить в фигурные скобки, а точку с запятой можно просто заменить. В левой части вы можете проверить, начинается ли оно с типа, и заменить этот бит. То, что остается в левой части, можно поместить в собственный набор фигурных скобок. Дайте мне знать, если вы не следите, и я опубликую пример.
Ответ №1:
Я довольно долго работал над вашей сложной проблемой манипулирования строками…
Я пришел с идеей «словаря», упрощающей управление заменами. И я использовал пробелы для выделения элементов string для переноса с <
помощью and >
.
Взгляните на комментарии в коде. CodePen
var input =
'int a = 0;'
'nint b = 5;'
'nint a = b 5;'
'nint c = a1 / 1;'
'ndouble a = 1;'
'nfloat a = 0;'
'na = 0;'
'nfloat a = b 1;'
'na = (b - c) * 5;'
'nlong int = (w - x) * 7;' // Added to test the two words types
'nlong double = (x - w) * 7;'; // Added to test the two words types
var dictionary = [
{
target: "long int",
replacement: "long|int" // | to ensure keeping that space, will be restored later
},
{
target: "long double",
replacement: "long|double" // | to ensure keeping that space, will be restored later
},
{
target: /=/g,
replacement: "assign_op"
},
{
target: /;/g,
replacement: "end_of_statement"
},
{
target: /(/g,
replacement: "open_parenthesis"
},
{
target: /)/g,
replacement: "close_parenthesis"
},
{
target: /[ -*/%]/g,
replacement: "operator"
},
{
target: / {2}/g,
replacement: "operator"
}
];
function translate(input) {
//console.log(input);
// Your unchanged regex
var regex3 = new RegExp(/(((int|long int|double|long double|float) s*([a-zA-Z_] d*)*|([a-zA-Z_] d*))s*=s*(([a-zA-Z_]*|[a-zA-Z_] d*)*|d*|d .d );)|(((int|long int|double|long double|float) s*([a-zA-Z_] d*)*|([a-zA-Z_] d*))s*=(s*(*(([a-zA-Z_]*|[a-zA-Z_] d*)*|d*|d .d ))*s*[ -/*%]s*(*(([a-zA-Z_]*|[a-zA-Z_] d*)*|d*|d .d ))*)*s*;)/g);
// An array of lines created by the use of your regex
var lines_array = input.match(regex3);
//console.log(lines_array);
// The result variable
var output = '';
// Process each lines
lines_array.forEach(line => {
// Use the dictionary to replace some special cases
// It adds spaces around the replacements to ensure word separation
dictionary.forEach(translation => {
if (line.match(translation.target)) {
line = line.replace(translation.target, " " translation.replacement " "); // Notice the spaces
}
});
// Remove double spaces
line = line.trim().replace(/s /g," ");
// Use the spaces to get a word array to add the angle brackets
var words = line.split(" ");
words.forEach(word => {
output = "<" word ">";
});
// Re-add the line return
output = 'n';
});
// Final fixes on the whole result string
output = output
.replace(/|/g, " ") // Restore the space in the "two words types" ( was replaced by a | )
.replace(/<</g, "<") // Remove duplicate angle brackets
.replace(/>>/g, ">")
console.log(output);
}
// Run the function
translate(input);