Member 12692000 Ответов: 1

Как сопоставить несколько шаблонов регулярных выражений в нескольких файлах и создать файл журнала?


Я хочу найти некоторые шаблоны регулярных выражений в файлах (*. txt), которые находятся внутри папки, путь к которой я указал в текстовом поле, и папка содержит другие подпапки с файлами txt в виде 12345-2031-30201\2031\30201\txt\110.txt и если шаблон совпадает даже в одном файле, то строка записывается в файл журнала, который создается внутри папки, путь к которой я указал в текстовом поле, а затем переходит к следующему регулярному выражению и так далее.

Проблема, с которой я сталкиваюсь, заключается в том, что файл журнала показывает только первый совпадающий шаблон и не показывает, совпадали ли другие шаблоны в каком-либо файле или нет. В основном происходит то, что программа открывает, скажем, первый файл и ищет первый шаблон, и она находит совпадение, поэтому она записывает текст, связанный с этим шаблоном "check figure link", и это все, что есть в файле журнала, но тот же файл(и некоторые другие файлы) действительно соответствует второму и третьему шаблону, но он не показывает тексты, связанные с этими шаблонами, такие как "check table link" и "check section link".

Кто-нибудь может помочь?

Что я уже пробовал:

Dim patterns = New List(Of String()) From {
({"Check figure link", "(?<!>)(figure|fig\.|figs\.|figures) (\d+)"}),
({"Check table link", "(?<!>)(table|tab\.|tabs\.|tables) (\d+)"}),
 ({"Check section link", "(?<!>)(section|sec\.|sect\.|section) (\d+)"}),
 ({"Check space", "</inline>w+"}),}

    Dim output = From pattern In patterns.AsParallel
                 Let regEx = New Regex(pattern(1), RegexOptions.Compiled)
                 From tFile In Directory.EnumerateFiles(TextBox1.Text, "*.txt", SearchOption.AllDirectories)
                 Where tFile Like "*\#*\#*\#*\txt\#*.txt" AndAlso regEx.IsMatch(File.ReadAllText(tFile))
                 Take 1
                 Select pattern(0)

    File.WriteAllLines(TextBox1.Text.TrimEnd("\"c) & "\Checklist.log", output)
    MsgBox("Process Complete")

Richard Deeming

Вы сказали нам, что вы хотите, чтобы ваш файл журнала содержал, но вы не сказали нам, какие выходные данные вы получаете, когда запускаете свой код.

Member 12692000

В основном мне нужен список, какие паттерны совпадали хотя бы один раз по крайней мере в одном файле, так как у меня есть около 200+ паттернов для поиска в файлах, но я не хочу проходить через все эти паттерны, я просто хочу найти совпадающие паттерны в моих файлах, а затем изменить их соответствующим образом.

Richard Deeming

Это все еще не говорит нам, какие выходные данные вы получаете, когда запускаете свой код.

Member 12692000

Выходные данные - это файл журнала, который создается при сопоставлении шаблона, а затем записывает текст, связанный с этим шаблоном, в файл журнала. Это все проясняет?

Richard Deeming

Нет.

Вы сказали нам, что вы хотеть случаться.

Вы показали нам код, который сейчас используете.

Но ты не рассказал нам, что происходит, когда вы запускаете этот код.

Member 12692000

Вы спрашиваете, что происходит не так в моем коде?

Richard Deeming

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

Patrice T

Воспользуйся Улучшить вопрос чтобы обновить ваш вопрос.
Чтобы каждый мог обратить внимание на эту информацию.

1 Ответов

Рейтинг:
7

Matt T Heffron

Таким образом, похоже, что вы хотите найти, какие файлы имеют ошибки в соответствии с шаблонами.
То, что у вас есть, даст вам до 4 линий в журнале указывается, какой тип ошибок существует где-то в иерархии файлов.
Это кажется очень неинформативным!
Не лучше ли было бы знать (по крайней мере) какой файл есть ошибки?
Не лучше ли было бы узнать какие ошибки есть ли в каждом из этих файлов?

Вот что я предлагаю.
(Это может быть совершенно не соответствует вашим требованиям, но то, что у вас есть, просто кажется большой работой для почти нулевого информационного содержания.)

То как вы это структурировали распараллеливание таково очень неэффективный, поскольку он читает каждый файл для каждого шаблона, поэтому каждый файл потенциально сканируется пять раз!
Распараллеливайте имена файлов.
Тогда это означает, что Regex экземпляры должны быть созданы и скомпилированы перед циклами выполнения.
Вы также читаете весь файл каждый раз. Паттерны, которые вы показали, не охватывают линии, поэтому сопоставляйте их с каждой линией по одному, чтобы избежать потенциально большого количества ввода-вывода.
Я извлек проверку каждого файла в функцию, чтобы она могла устранить избыточный ввод-вывод и Regex соответствие.
Я также упростил Regex узоры.
Что-то вроде (мой VB ржавый):

'Edited MTH: based on your comment...
Dim patterns = New List(Of String()) From {
     ({"Check figure link", "(?<!>)(?:figures?|figs?\.) \d+"}),
     ({"Check table link", "(?<!>)(?:tables?|tabs?\.) \d+"}),
     ({"Check section link", "(?<!>)(?:sections?|sect?\.) \d+"}),
     ({"Check space", "</inline>\w+"})}

Dim compiledPatterns = New Dictionary(Of Regex, String)
For Each pat As String() In patterns
    compiledPatterns.Add(New Regex(pat(1), RegexOptions.Compiled), pat(0))
Next

'Edit: Setup to "transpose" the information collected below.
'This would be tricky to do combined with parallelization.
'So it is done as a sequential pass through the collected info.
Dim pathsByMessage = New Dictionary(Of String, List(Of String))
For Each pat As String() In patterns
    pathsByMessage.Add(pat(0), New List(Of String))
Next

Dim filteredFilenames = From tFile In Directory.EnumerateFiles(TextBox1.Text, "*.txt", SearchOption.AllDirectories)
             Where tFile Like "*\#*\#*\#*\txt\#*.txt"

Dim output = From tFile In filteredFilenames.AsParallel
               Let checks = CheckFile(tFile, compiledPatterns)
               Where checks.Any
               Select Path = tFile, Messages = checks

'Edit: Now "transpose" this
'It's OK to process this *sequentially*, even if the query is still running parallelized!
For Each pm In output
    For Each msg In pm.Messages
        pathsByMessage(msg).Add(pm.Path)
    Next
Next

File.WriteAllLines(TextBox1.Text.TrimEnd("\"c) & "\Checklist.log",
                   From pbm In pathsByMessage
                     Where pbm.Value.Any
                     Select String.Format("""{0}""=={1}", pbm.Key, vbNewLine & String.Join(vbNewLine, pbm.Value)))
MsgBox("Process Complete")

И
Function CheckFile(tFile As String, compiledPatterns As Dictionary(Of Regex, String)) As List(Of String)
    'structure this to eliminate redundant checking
    Dim messages As New List(Of String)
    Dim checks = New HashSet(Of Regex)(compiledPatterns.Keys)

    For Each line In File.ReadLines(tFile)
        If Not checks.Any Then
            Exit For
        End If
        For Each re In checks.ToList
            If re.IsMatch(line) Then
                messages.Add(compiledPatterns(re))
                checks.Remove(re)
            End If
        Next
    Next

    Return messages
End Function


Member 12692000

@Matt ваше решение, кажется, немного отличается от того, что я ищу, как мне сделать так, чтобы файл журнала показывал ошибки следующим образом

"Проверить рисунке ссылка"==
D:\test\bk\1235-12-3053\230\124\txt\124.txt
D:\test\bk\1235-12-3053\230\131\txt\131.txt
"Проверить ссылку на таблицу"==
D:\test\bk\1235-12-3053\230\124\txt\124.txt
D:\test\bk\1235-12-3053\230\205\txt\205.txt
и так далее

А также, не могли бы вы объяснить свое кодирование(как оно работает), поскольку я новичок в этом деле? vb.net или в любом типе кодирования, если уж на то пошло !!

Member 12692000

Спасибо, приятель..

Maciej Los

5ед!

Matt T Heffron

Спасибо!