6

I have several large txt files the following examples:

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

My goal is to search for all the math operations and replace them with its results, like this:

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

Is there any way to automate this in Notepad++?

9
  • 1
    Possible Stack Overflow duplicate: Notepad++ Regular Expression add up numbers recommends using a python script. – DavidPostill – DavidPostill Sep 4 '15 at 15:23
  • Could you point me in the right direction on how to start? – Luis Guerreiro Sep 4 '15 at 15:45
  • Sorry, I don't speak python. – DavidPostill Sep 4 '15 at 15:48
  • 1
    Why does data="32/3" should be replaced with data="5.333333"? Actually 32/3 = 10,666666666666..., am I missing something?. How many fractional digits do you need after the number has been rounded? – omegastripes Sep 4 '15 at 20:39
  • 1
    The last expression in the example data"57.38" has no equal sign, is that right formatting, and such expressuons should also be evaluated? – omegastripes Sep 5 '15 at 7:30
5

You can automate that in Notepad++ by creating shortcut to external VBScript. Here is the script:

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

Do the following:

  • Save this script to file, eg C:\Test\MathResults.vbs
  • Open your text file in Notepad++
  • Click Menu - Run (or F5)
  • Enter "C:\Test\MathResults.vbs" "$(FULL_CURRENT_PATH)" including quotes into The Program to Run field
    specify the path
  • Click Save...
  • Create shortcut, entering eg MathResults as name and Ctrl + F7 as hot keys
    choose the hot keys
  • Click OK
  • Click Run

Now your shortcut has been saved in configuration file, you can just open text files, press Ctrl + F7, once the script completes processing, reload dialog appears, click Yes to display changed file (you may setup the file to be reloaded automatically after been changed). That's it.

BTW, this script works standalone perfectly, you can select in explorer window or on desktop number of files and folders to be processed, and then drop it to the script file.

4
  • You sir,are a genius! This worked perfectly. Thank you so much! – Luis Guerreiro Sep 5 '15 at 6:55
  • Just one more question, what if there are some math operations inside the file, like this: data="12*(4+9)" What changes do I need to do in the script? – Luis Guerreiro Sep 5 '15 at 7:06
  • 2
    I've changed regex pattern to (\w+=)"([\.\d\(\)\\\*\+/-]*)" accoring to requirements: equal sign is a must, expressions with parentheses are also evaluated. – omegastripes Sep 5 '15 at 8:02
  • 1
    Worked flawlessly! You made my day! Thanks again! – Luis Guerreiro Sep 5 '15 at 8:14
4

Not possible with pure Notepad++ techniques. But you could use Powershell to do the work and use it from within Notepad++

Before & after

enter image description hereenter image description here

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

Explanation

  • The Regex pattern (?<=data=").*?(?=") uses a look-ahead and a look-behind to capture everything between data=" and the very next ". This way you get the strings 32/3, 0.0237/4 and 28.69*2 for your example
  • Next, we use Invoke-Expression to calculate mathematical results from those strings. You get 10.6666666666667, 0.005925 and 57.38
  • A quick Math::Round(x,6) rounds results to 6 fractional digits if necessary
  • Now we use a regex search and replace to search the current formula string over the whole file (remember, we are in a loop) and replace it with our calculated result
  • Last step is to write the modified content to any desired output file

Nothing special. The hardest part was to find out, how to replace special chars (* is such one). Here comes [regex]::Escape() to the rescue.


The script can be used from within Notepad++ the same way @omegastripes has already described.

  1. In Notepad++ press F5 and enter:

    Powershell -File "C:\your\path\to\EvaluateFormulas.ps1" "$(FULL_CURRENT_PATH)"
    
  2. Click Save and define a shortcut

Caveats

In the current state, all changes are saved to file immediately. Make a backup before running it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.