Воскресенье, 12.01.2025, 01:20
Приветствую Вас Гость | RSS

блокнот

article

Главная » Статьи » Шарпомир » c#

работа с регэкспами

Цель : Разработать программу, работающую с кодом языка высокого уровня. Язык программы и анализируемого модуля любой!

Возможности программы:

анализировать модуль на выбранном языке программирования и выдавать отчет в виде текста, оформленного по своему пониманию. Отчет должен содержать следующие данные по каждой процедуре, функции и «тела» модуля:

1) Название процедуры или функции

Входные данные данной процедуры или функции:

2) список всех параметров процедуры или функции с указание типа переменных;

3) список используемых глобальных переменных, как входных данных с указанием типа этих переменных;

4) список используемых внешних файлов как входных данных с указанием пути на жёстком диске;

5) и любую другую входную информацию, не попавшую в выше указанную классификацию;

Выходные данные данной процедуры или функции:

6) список всех параметров процедуры или функции, которые являются выходными данными, с указание типа переменных;

7) список используемых глобальных переменных, как выходных данных с указанием типа этих переменных;

8) список используемых внешних файлов как выходных данных с указанием пути на жёстком диске;

9) и любую другую выходную информацию, не попавшую в выше указанную классификацию.

описанные в заданиях 1-ой, 2-ой и 3-ей лабораторных работах ТЯПиМТ.

следующие дополнительные возможности, зависящие от номера студента в списке его группы:

1. номер в списке кратный единице: производить многокритериальный поиск строки в модуле выбранного языка высокого уровня. Искомая строка должна удовлетворять следующим условиям:

в искомой строке должна быть найдена заданная пользователем подстрока1;

в искомой строке должна быть найдена заданная пользователем подстрока2. Пользователь так же может отключить этот параметр;

в искомой строке должна быть найдена заданная пользователем подстрока3. Пользователь так же может отключить этот параметр;

в искомой строке должно быть найдено ключевое слово, заданное пользователем, которое определяется типом оператора (или части оператора) языка. К, примеру,

ключевое слово – «Если», тип оператора – «условие»;

ключевое слово – «Для», тип оператора – «Цикл»;

ключевое слово – «Процедура», тип оператора – «объявление процедуры»;

5) в строке не должно быть подстроки1. Пользователь так же может отключить этот параметр;

6) в строке не должно быть подстроки2. Пользователь так же может отключить этот параметр.

Если в модуле есть несколько строк, удовлетворяющих перечисленным условиям, то необходимо вывести таблицу с колонками:

1–ая колонка: Номер найденной строки в модуле;

2–ая колонка: Текст найденной строки.

Немного теории

Для работы с регулярными выражениями в C# предусмотрен класс System.Text.RegularExpressions.Regex. Структура регулярных выражения полностью аналогична регулярным выражениям, используемым в PHP. Для выполнения поиска по строке, замены, или выделения некоторых блоков используются различные методы ранееупомянутого класса. Текст регулярного выражения передается в конструктор Regex'a (хотя это не обязательно, ибо его можно передать и непосредственно в нужный Вам метод).

Об этих методах сейчас и пойдет речь.

Подходит-ли строка под регулярное выражение

Для проверки того, подходит-ли строка под регулярное выражение используется методRegex.IsMatch (), возвращающий true если текст подходит под регулярное выражение и false если нет. Его конструктор может принимать следующие наборы данных:

IsMatch(string input, int startat)

Здесь input — обрабатываемая строка, а startat — позиция в строке, с которой следует начинать поиск. Применяется регулярное выражение, ранее переданное в конструктор класса Regex.

IsMatch(string input)

input — обрабатываемая строка. Применяется регулярное выражение, ранее переданное в конструктор класса Regex.

IsMatch(string input, string pattern, System.Text.RegularExpressions.RegexOptions options)

input — обрабатываемая строка, pattern — регулярное выражение, options — набор опций проверки. О них поговорим чуть позже.

IsMatch(string input, string pattern)

input — обрабатываемая строка, pattern — регулярное выражение.

RegexOptions

Этот класс предстваляет собой набор опций, применяемых к регулярному выражению.

Compiled — указывает на то, скомпилировано-ли регулярное выражение в сборку (Assembly). Это ускоряет процесс применения регулярного выражения, но увеличивает время загрузки программы.

CultureInvariant — указывает на то, следует-ли пропускать культурные различия в тексте (например, в Англии цвет — colour, а в Америке — color).

ECMAScript — включает ECMAScript-совместимость регулярных выражений. Обычно используется в связке с опцией IgnoreCase.

IgnoreCase — указывает на то, что в обрабатываемом тексте не следует учитывать регистр букв.

IgnorePatternWhitespace — удаляет из тела регулярного выражения неэкранированный пробел и дает возможность использовать комментарии после символа #

Multiline — многострочный режим. Позволяет использовать директивы ^ и $ как символы начала и конца каждой линии.

None — пустая опция.

RightToLeft — указывает на то, что поиск следует производить справа налево, а не слева направо.

Singleline — однострочный режим. Изменяет значение точки (.) так, что она может представлять любой символ (включая символ переноса строки — n).

Замена текста

Для замены текста с помощью регулярынх выражений используется метод Regex.Replace (), возвращающий string-строку с измененным текстом. Основные способы передачи данных в его конструктор:

Replace(string input, string pattern, string replacement)

Здесь input — обрабатываемая строка, pattern — текст регулярного выражения, а replacement — текст, на который надо заменить найденные области.

Replace(string input, string pattern, string replacement, System.Text.RegularExpressions.RegexOptions options)

Опять-же input — обрабатываемая строка, pattern — текст регулярного выражения,replacement — текст, на который надо заменить найденные области. options — набор опций поиска (см. выше).

Replace(string input, string replacement)

input — обрабатываемая строка, replacement — заменяющий текст. Применяется регулярное выражение, ранее переданное в конструктор класса Regex.

Replace(string input, string replacement, int count)

Полностью аналогичен предыдущему примеру, за исплючением параметра count, который обозначает максимальное количество выполняемых замен.

Разбиение строки

Для разбиения строки на части используется метод Regex.Split (), который возвращает массив строк (string[]) с частями исходной строки. Основные способы передачи данных в конструктор:

Split(string input, string pattern)

Разбивает строку input на части, описанные в регулярном выражении pattern.

Split(string input, int count)

Разбивает строку input на части, описанные в регулярном выражении, которое было передано в конструктор класса Regex. Возвращает максимум count подстрок.

Поиск совпадений

Для поиска совпадений используется метод Regex.Matches (). Этот метод возвращает массив класса MatchCollection, содержащий найденные совпадения и ряд другой информации.

Доступ к найденному тексту производится с помощью конструкции match[i].Value. Получить количество найденных совпадений можно из свойства match.Count.

Конструкторы класса:

Matches(string input, string pattern)

input — обрабатываемый текст, pattern — текст регулярного выражения.

Matches(string input, string pattern, System.Text.RegularExpressions.RegexOptions options)

Аналогичен предыдущему, но позволяет задать опции поиска (см. выше).

Matches(string input, int startat)

Выполняет поиск с позиции startat строки string. Применяется регулярное выражение, переданное в конструктор класса Regex.

Листинги программ

Листинг Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions; // для работы с регулярными выражениями

namespace kurs
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

public StringBuilder logerStr = new StringBuilder();

public class findStr
{
public int nomerStr; // номер строки
public String samaStr; // сама строка
public bool incl; // включена или выключена
}

public List strList = new List(); // список найденных строк


// функция поиска строки по заднному шаблону
// с дальнейшим формированием группы
private void searchReg(string strpat,string group , string nameStr){
Regex regex = new Regex(strpat);
MatchCollection matches = regex.Matches(codeBox.Text);
string text = "";

foreach (Match matche in matches)
{
text += matche.Groups[group].Value + "\r\n";
}

logBox.AppendText(nameStr+" \r\n");
logBox.AppendText(text);
logBox.AppendText("------------------------------------------------------------\r\n");

logerStr.Append(nameStr + " \r\n");
logerStr.Append(text);
logerStr.Append("------------------------------------------------------------\r\n");
}

// поиск фаилов в коде без формирования групп
private void searchRegFiles(string strpat, string nameStr)
{
Regex regex = new Regex(strpat);
MatchCollection matches = regex.Matches(codeBox.Text);
string text = "";

foreach (Match matche in matches)
{
text += matche.Value + "\r\n";
}

logBox.AppendText(nameStr + " \r\n");
logBox.AppendText(text);
logBox.AppendText("------------------------------------------------------------\r\n");

logerStr.Append(nameStr + " \r\n");
logerStr.Append(text);
logerStr.Append("------------------------------------------------------------\r\n");
}

// парсинг функции
private void searchRegF(string strpat, string group, string nameStr)
{
Regex regex = new Regex(strpat);
MatchCollection matches = regex.Matches(codeBox.Text);

Regex regexParam = new Regex(@"\(.+\)");

string text = "";
string[] st, st1;
logBox.AppendText(nameStr + " \r\n");
logerStr.Append(nameStr + " \r\n");
foreach (Match matche in matches)
{
text += matche.Value + "\r\n";
st1 = matche.Value.Split('(');
st = st1[0].Split(' ');

Match matchesParam = regexParam.Match(matche.Value);

string sub = matchesParam.Value.Substring(1, matchesParam.Value.Length-2);

logBox.AppendText("Имя функции: " + st[2] + " \r\n");
logBox.AppendText("Модификатор функции: " + st[0] + " \r\n");
logBox.AppendText("Тип функции: " + st[1] + " \r\n");
logBox.AppendText("Параметры функции: " + sub + " \r\n");
logBox.AppendText("\n");

logerStr.Append("Имя функции: " + st[2] + " \r\n");
logerStr.Append("Модификатор функции: " + st[0] + " \r\n");
logerStr.Append("Тип функции: " + st[1] + " \r\n");
logerStr.Append("Параметры функции: " + sub + " \r\n");
logerStr.Append("\n");

}

logBox.AppendText("------------------------------------------------------------\r\n");
logerStr.Append("------------------------------------------------------------\r\n");
}

// поиск процедуры в коде
private int searchProcedure(string strpat, string nameStr)
{
Regex regex = new Regex(strpat);
MatchCollection matches = regex.Matches(nameStr);
foreach (Match matche in matches)
{
return 1;
}
return -1;
}


private void openFile_Click(object sender, EventArgs e)
{
// открытие фаила с кодом для парсинга
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "Файлы cs (*.cs)|*.cs";
if (dlg.ShowDialog() != DialogResult.OK)
return;
if (File.Exists(dlg.FileName))
codeBox.Text = File.ReadAllText(dlg.FileName, Encoding.UTF8);
}


private void parseCode_Click(object sender, EventArgs e)
{
logBox.Clear();
// функции поиска
// первый параметр - регулярное выражение
//второй - группы(если есть)
// название для вывода в лог
searchReg(@"class\s+(?\w+)","class","КЛАССЫ:");
searchReg(@"using\s+(?\w+)", "using", "ПРОСТРАНСТВА ИМЕН:");
searchRegF(@"[a-zA-Z]+\s+\S+\s+[a-zA-Z0-9]+\(.+\)(\s|\n|\r|\t)*\{", "func", "ФУНКЦИИ:");
searchRegFiles(@".:\\.+\.[A-Za-z]+", "ФАИЛЫ:");

}

private void fullScr_Click(object sender, EventArgs e)
{
Log frm = new Log(this);// открытие формы с логом
frm.Show();
}

private void btnFind_Click(object sender, EventArgs e)
{
string[] tempArray = codeBox.Lines;// определение массива строк из текста кода
strList.Clear(); // чистим список найденных строк

for (int counter = 0; counter < tempArray.Length; counter++)
{
// поиск строк по 1 условию
if (subString1.Text != "")
{
int i = tempArray[counter].IndexOf(subString1.Text);
if (i != -1)
{
findStr istr = new findStr();
istr.nomerStr = counter;
istr.samaStr = tempArray[counter];
istr.incl = true;
strList.Add(istr);
}
}
//поиск строк по 2 условию
if ((subString2.Text != "") && (str2off.Checked == false))
{
int i = tempArray[counter].IndexOf(subString2.Text);
if (i != -1)
{
findStr istr = new findStr();
istr.nomerStr = counter;
istr.samaStr = tempArray[counter];
istr.incl = true;
strList.Add(istr);
}
}
// поиск строк по 3 условию
if ((subString3.Text != "") && (str3off.Checked == false))
{
int i = tempArray[counter].IndexOf(subString3.Text);
if (i != -1)
{
findStr istr = new findStr();
istr.nomerStr = counter;
istr.samaStr = tempArray[counter];
istr.incl = true;
strList.Add(istr);
}
}
// поиск строк по содержащих условия
if ((comb.Text != "") && (comb.Text == "условие"))
{
int i = tempArray[counter].IndexOf("if");
if (i != -1)
{
findStr istr = new findStr();
istr.nomerStr = counter;
istr.samaStr = tempArray[counter];
istr.incl = true;
strList.Add(istr);
}
}

// поиск строк содержащих циклы
if ((comb.Text != "") && (comb.Text == "цикл"))
{
int i = tempArray[counter].IndexOf("for");
if (i != -1)
{
findStr istr = new findStr();
istr.nomerStr = counter;
istr.samaStr = tempArray[counter];
istr.incl = true;
strList.Add(istr);
}
}

// поиск строк с объявлением процедур
if ((comb.Text != "") && (comb.Text == "процедура"))
{
int i = searchProcedure(@"[a-zA-Z]+\s+\w+\s+[a-zA-Z0-9]+\(.+\)", tempArray[counter]);

if (i != -1)
{
findStr istr = new findStr();
istr.nomerStr = counter;
istr.samaStr = tempArray[counter];
istr.incl = true;
strList.Add(istr);
}
}
}
//исключить поиск строк по 1 условию
for (int counter = 0; counter < strList.Count; counter++)
{
if ((subString1q.Text != "") && (str1offq.Checked == false))
{
int i = strList[counter].samaStr.IndexOf(subString1q.Text);
if (i != -1)
strList[counter].incl = false;


}
//исключить поиск строк по 2 условию
if ((subString2q.Text != "") && (str2offq.Checked == false))
{
int i = strList[counter].samaStr.IndexOf(subString2q.Text);
if (i != -1)
strList[counter].incl = false;
}
}

table frm= new table(this); // вывод результата поиска в таблицу
frm.Show();
}




}
}


Листинг Log.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace kurs
{
public partial class Log : Form
{
Form1 frm;
public Log(Form1 frm)
{
InitializeComponent();
this.frm = frm;
}

private void Log_Load(object sender, EventArgs e)
{
loggerText.AppendText(frm.logerStr.ToString());
}
}
}

Листинг table.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace kurs
{
public partial class table : Form
{
Form1 frm;
public table(Form1 frm)
{
InitializeComponent();
this.frm = frm;
}
// вывод данных из списка найденных строк в таблицу
private void table_Load(object sender, EventArgs e)
{
for (int counter = 0; counter < frm.strList.Count; counter++)
if (frm.strList[counter].incl)
grid.Rows.Add(frm.strList[counter].nomerStr.ToString(), frm.strList[counter].samaStr);

}
}
}

Результаты работы:

Рис 1. Открытие фаила

Рис 2. Открытие фаила proga.cs с кодом, который надо распарсить

Рис 3. Сам код

Рис 4. Кнопка для парсинга

Рис 5. Результат парсинга

Если посмотреть подробно, то определили:

КЛАССЫ:
Program
------------------------------------------------------------
ПРОСТРАНСТВА ИМЕН:
System
------------------------------------------------------------
ФУНКЦИИ:
Имя функции: ReturnMe
Модификатор функции: static
Тип функции: Int64
Параметры функции: Int64 N

Имя функции: Main
Модификатор функции: static
Тип функции: void
Параметры функции: string[] args

------------------------------------------------------------
ФАИЛЫ:
F:\folder\54.txt
C:\1.txt
------------------------------------------------------------

Рис 5. Поиск по коду и вывод результата в таблицу

Рис 6. Поиск по коду и вывод результата в таблицу

Как видно процедуры продублировались, что является верным , так как в начальном условии не было задания исключить повторяющиеся строки. Они получились из-за того что в строках процедур есть спецификатор static.

Рис 5. Поиск по коду и вывод результата в таблицу

Отключим static и получим другой результат

Категория: c# | Добавил: gen (21.03.2011)
Просмотров: 1749
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

EzH->

link

Категории раздела

c# [8]
.net winforms [2]
asp.net [1]

депозит

Поиск