6

У меня есть несколько больших текстовых файлов следующих примеров:

data="32/3"
count id="3" data="0.0237/4"
ext min="1" max="3" data="28.69*2"

Моя цель - найти все математические операции и заменить их результатами, например так:

data="10.666667"
count id="3" data="0.005925"
ext min="1" max="3" data="57.38"

Есть ли способ автоматизировать это в Notepad++?

2 ответа2

5

Вы можете автоматизировать это в Notepad++, создав ярлык для внешнего VBScript. Вот сценарий:

Option Explicit

Const FileEncoding = 0 ' 0 = ASCII, -1 = Unicode, -2 = System Default
Const FractDigits = 6 ' number of fractional digits

Dim objList, strPath

If WScript.Arguments.Count = 0 then
    CreateObject("WScript.Shell").PopUp "Drop folder(s) and / or file(s) to the script to process", 3, , 48
    WScript.Quit
End If

Set objList = ReadContent(WScript.Arguments)

If objList.Count = 0 Then
    CreateObject("WScript.Shell").PopUp "No files found", 3, , 48
    WScript.Quit
End If

With CreateObject("VBScript.RegExp")
    .Global = True
    .MultiLine = True
    .IgnoreCase = False
    .Pattern = "(\w+=)""([\.\d\(\)\\\*\+/-]*)"""
    For Each strPath In objList
        WriteToFile .Replace(objList(strPath), GetRef("FnReplace")), strPath, FileEncoding
    Next
End With
CreateObject("WScript.Shell").PopUp "Completed", 1, , 64

Function FnReplace(strMatch, strSubMatch1, strSubMatch2, lngPos, strSource)
    Dim strResult
    On Error Resume Next
    strResult = CStr(Round(Eval(strSubMatch2), FractDigits))
    If Err Then
        Err.Clear
        FnReplace = strMatch
    Else
        FnReplace = strSubMatch1 & """" & strResult & """"
    End If
End Function

Function ReadContent(arrList)
    Dim objList, strPath
    Set objList = CreateObject("Scripting.Dictionary")
    For Each strPath In arrList
        AddContent strPath, objList
    Next
    Set ReadContent = objList
End Function

Sub AddContent(strPath, objList)
    Dim objItem
    With CreateObject("Scripting.FileSystemObject")
        If .FileExists(strPath) Then
            objList(strPath) = ReadFromFile(strPath, FileEncoding)
        End If
        If .FolderExists(strPath) Then
            For Each objItem In .GetFolder(strPath).Files
                AddContent objItem.Path, objList
            Next
            For Each objItem In .GetFolder(strPath).SubFolders
                AddContent objItem.Path, objList
            Next
        End If
    End With
End Sub

Function ReadFromFile(strPath, intFormat)
    With CreateObject("Scripting.FileSystemObject").OpenTextFile(strPath, 1, False, intFormat)
        ReadFromFile = ""
        If Not .AtEndOfStream Then ReadFromFile = .ReadAll
        .Close
    End With
End Function

Sub WriteToFile(strCont, strPath, intFormat)
    With CreateObject("Scripting.FileSystemObject").OpenTextFile(strPath, 2, True, intFormat)
        .Write(strCont)
        .Close
    End With
End Sub

Сделайте следующее:

  • Сохраните этот скрипт в файл, например, C:\Test\MathResults.vbs
  • Откройте свой текстовый файл в Notepad++
  • Нажмите Меню - Выполнить (или F5)
  • Введите "C:\Test\MathResults.vbs" "$(FULL_CURRENT_PATH)" включая кавычки в поле "Программа для запуска"
    указать путь
  • Нажмите Сохранить ...
  • Создайте ярлык, введя, например, MathResults в качестве имени и Ctrl + F7 в качестве горячих клавиш
    выберите горячие клавиши
  • Нажмите ОК
  • Нажмите Run

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

Кстати, этот скрипт отлично работает автономно, вы можете выбрать в окне проводника или на рабочем столе количество файлов и папок, которые нужно обработать, а затем перетащить его в файл скрипта.

4

Невозможно с чистыми методами Notepad++. Но вы можете использовать Powershell для выполнения работы и использовать ее из Notepad++

До после

EvaluateFormulas.ps1

$Content = Get-Content -Path $Args[0]

$Formulas = ($Content | Select-String -Pattern '(?<=data=").*?(?=")' -AllMatches).Matches

ForEach ($Formula in $Formulas){
    $Result = Invoke-Expression -Command $Formula.Value
    $Result = [Math]::Round($Result,6)
    $Content = $Content -Replace [Regex]::Escape($Formula), $Result
}
Set-Content -Path $Args[0] -Value $Content

объяснение

  • Шаблон регулярных выражений (?<=data=").*?(?=") использует упреждающий просмотр и упущение для захвата всего, что находится между data=" и последующими " . Таким образом, вы получите строки 32/3, 0,0237/4 и 28,69 * 2 для вашего примера.
  • Далее мы используем Invoke-Expression для вычисления математических результатов из этих строк. Вы получаете 10,6666666666667, 0,005925 и 57,38.
  • Быстрый Math::Round(x,6) округляет результаты до 6 дробных цифр, если необходимо
  • Теперь мы используем поиск и замену регулярных выражений для поиска текущей строки формулы по всему файлу (помните, что мы находимся в цикле) и заменяем ее вычисленным результатом.
  • Последний шаг - записать измененный контент в любой желаемый выходной файл.

Ничего особенного. Самым сложным было выяснить, как заменить специальные символы (* такой). Здесь на помощь приходит [regex]::Escape() .


Сценарий можно использовать из Notepad++ так же, как уже описал @omegastripes.

  1. В Notepad++ нажмите F5 и введите:

    Powershell -File "C:\your\path\to\EvaluateFormulas.ps1" "$(FULL_CURRENT_PATH)"
    
  2. Нажмите Сохранить и определите ярлык

Предостережения

В текущем состоянии все изменения сразу сохраняются в файл. Сделайте резервную копию перед запуском

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .