使用正则表达式替换TextArea中的文本正在创建新行

时间:2017-03-14 14:37:06

标签: regex vbscript hta

我正在创建一个HTML应用程序,允许用户自由键入textarea,然后在一个input框中输入正则表达式模式,并将一个替换字符串转换为第二个input盒子。当用户按下按钮时,将运行VBScript序列,该序列接受用户输入,创建正则表达式并用字符串替换该模式。我的问题是,当用户选择一行的结尾,即$的模式时,替换字符串将添加到每一行,而介于每一行。

例如,以下文字:

Test
Test
Test

如果输入@的替换字符串将输出为:

Test@
@
Test@
@
Test@

如何防止“附加”线出现在输出中?是什么原因导致了他们?

申请代码如下:

<!doctype html>
<head>
<hta:application
    id="regexpengine"
    applicationname="RegExpEngine"
    icon="S:\Technical Projects\TechProd VB Projects\SPF Creator\SPF Creator\tools.ico"
    singleinstance="yes"
    border="thick"
    borderstyle="complex"
    scroll="yes"
    maximizebutton="no"
    version="0.1" />
<title>Regular Expression Engine</title>
<meta http-equiv="x-ua-compatible" content="ie=8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<script language="VBScript">
    ' Set Global Variables

        'Core Objects
        Set objFSO = CreateObject("Scripting.FileSystemObject")

        'Input/Event Variables
        strInput = "No User Input"
        strExp = Empty
        strReplace = Empty
        strOutput = Empty
        strUserFunction = Empty
        strInstruction = Empty
        strUserConfirmedAction = Empty
        strOriginalInput = Empty

        'Custom Objects
        objRecord = False
        objGUIOption = "Type"

    Sub Window_onLoad()
    'Load Previously Entered Data if Available

        'Check that RAWFiles.txt exists and load any contained text
        'If objFSO.FileExists("C:\Temp\RAWFiles.txt") Then
        ''  Set objFileSize = objFSO.GetFile("C:\Temp\RAWFiles.txt")
        ''  If objFileSize.size > 0 Then
        ''      Set objFile=objFSO.OpenTextFile("C:\Temp\RAWFiles.txt",1)
        ''      strFileList=objFile.ReadAll
        ''      document.all.FileList.value=strFileList
        ''      objFile.Close
        ''  End If
        'End If

        'Load Previous Folder Values if Available
        'If objFSO.FileExists("C:\Temp\FolderLocation.txt") Then
        ''  Set objFileSize = objFSO.GetFile("C:\Temp\FolderLocation.txt")
        ''  If objFileSize.size > 0 Then
        ''      Set objFile=objFSO.OpenTextFile("C:\Temp\FolderLocation.txt",1)
        ''      strInputfolder=objFile.ReadLine
        ''      strOutputfolder=objFile.ReadLine
        ''      document.all.inputFolder.value=strInputfolder
        ''      document.all.outputFolder.value=strOutputfolder
        ''      objFile.Close
        ''  End If
        'End If

        'Force Window Size & Position
        window.resizeTo 885,750
        window.moveTo (screen.width - 885)/2, (screen.height - 750)/2

        'Hide File Input Option Until Selected
        document.all.selectFolder.style.display = "none"
        document.all.fileContents.style.display = "none"
    End Sub

    Sub UpdateMessage(strMessage,objType)
    'Update Message Area for Errors & User Decisions
        If objType = 2 Then
            LogArea.innerHTML = "<span class='error'>Error: " & strMessage & "</span><br>"
        Else
            LogArea.innerHTML = "<span class='update'>Message: " & strMessage & "</span><br>"
        End If
    End Sub

    Sub RunExpression
    'Take User Input & Run Expression Against File

        'Set Regular Expression
        Set objRegExp = New RegExp
        If strUserFunction="Replace" Then
            'Pattern for Replace Function - finds the first matched instance and then terminates
            With objRegExp
                .Pattern = strExp
                .IgnoreCase = False
                .Global = False
            End With
        Elseif strUserFunction="ReplaceAll" OR strUserFunction="Find" Then
            'Pattern for ReplaceAll & Find Functions - finds every matched instance
            With objRegExp
                .Pattern = strExp
                .IgnoreCase = False
                .Global = True
                .Multiline = True
            End With
        End If

        'Reset Output String
        strOutput = Empty

        'Perform User Selected Function
        If strUserFunction = "Replace" OR strUserFunction = "ReplaceAll" Then
            'Perform Replace - if the user input errors then capture the reason and end sequence

            On Error Resume Next
                'Replace on strReplace ensures that users can add in newlines using a standard \n
                strOutput = objRegExp.Replace(strInput,Replace(strReplace,"\n",vbNewLine))
            If Err.Number <> 0 Then
                Msgbox "Regular Expression Not Recognised",16,"Incorrect Syntax"
                Err.Clear
                UpdateMessage "Regular Expression Not Recognised - Incorrect Syntax - Instruction Failed",2
                strInstruction = Empty
                Exit Sub
            End If
        Elseif strUserFunction = "Find" Then
            Set objFind = objRegExp.Execute(strInput)
            strOutput = "Total Matches: " & objFind.Count & vbCRLF
            For Each Match in objFind
                strOutput = strOutput & "Matched: " & Match.Value & vbCRLF
            Next
            'Prevent Find Instructions from Being Committed
            strInstruction = Empty
        Else
            UpdateMessage "Run Attempted Without User Input - Run Terminated",2
            strInstruction = Empty
            Exit Sub
        End If

        'Write the Output to the Application Window - if the string has been replaced completely with a null value, output {EMPTY}
        If strOutput = "" Then
            expOutput.innerHTML = "{EMPTY}"
        Else
            document.getElementById("expOutput").appendChild(document.createTextNode(strOutput))
        End If

        'Inform User & Update if Recording
        If objRecord = True Then
            UpdateInput
            UpdateMessage "Performed Instruction Succesfully - Input Updated",1
            expOutput.innerHTML = "{RECORDING}"
        Else
            UpdateMessage "Performed Instruction Successfully",1
        End If
    End Sub

    Sub GetUserInput(strFunction)
    'Pull In User Input from Interface

        'Reset Error Message
        expOutput.innerHTML = ""

        'Determine Which Function was Requested (which button was pressed)
        strUserFunction = strFunction

        'Set User Input Data
        If userInputMethod.selectInputMethod(0).checked Then
            If Not userInput.Value = "" Then
                strInput = userInput.Value
            Else
                UpdateMessage "Free Typed Input is Selected but Textarea is Blank",2
                Exit Sub
            End If
        Elseif userInputMethod.selectInputMethod(1).checked Then
            If Not fileContents.Value = "" Then
                strInput = fileContents.Value
            Else
                UpdateMessage "Selected File is Blank",2
                Exit Sub
            End If
        Else
            Exit Sub
        End If

        'Set Expression
        If Not inputExp.Value = "" Then
            strExp = inputExp.Value
        Else
            UpdateMessage "No Expression Entered",2
            Exit Sub
        End If

        'Set Replace
        If Not replaceExp.Value = "" Then
            strReplace = replaceExp.Value
        Else
            strReplace = ""
        End If

        'Save Instruction
        If objRecord = True Then
            If Not strInstruction = Empty Then
                strInstruction = strInstruction & vbCRLF & strUserFunction & "," & strExp & "," & strReplace
            Else
                strInstruction = strUserFunction & "," & strExp & "," & strReplace
            End If
        Else
            strInstruction = strUserFunction & "," & strExp & "," & strReplace
        End If

        RunExpression
    End Sub

    Sub ChooseTextArea
    'Display User Input Textarea

        'Update GUI
        document.all.userInput.style.display="block"
        document.all.selectFolder.style.display="none"
        document.all.fileContents.style.display = "none"

        'Set Choice
        objGUIOption = "Type"
    End Sub

    Sub ChooseFile
    'Display File Input

        'Update GUI
        document.all.userInput.style.display="none"
        document.all.selectFolder.style.display="inline"
        If Not fileContents.Value = "" Then
            document.all.fileContents.style.display = "block"
        End If

        'Set Choice
        objGUIOption = "File"
    End Sub

    Sub UploadSelectedFile
    'Check User Selected File Exists & Load Contained Text

        'Reset Error Message
        expOutput.innerHTML = ""

        'Get User Input & Sanitise
        objFilePath = fileInput.Value
        objFilePath = Replace(objFilePath,chr(34),"")

        'Extract Data from File
        If objFSO.FileExists(objFilePath) Then
            Set objFileSize = objFSO.GetFile(objFilePath)
            If objFileSize.size > 0 Then
                Set objFile=objFSO.OpenTextFile(objFilePath,1)
                strFileContents=objFile.ReadAll
                document.all.fileContents.value=strFileContents
                objFile.Close
            Else
                UpdateMessage "Selected Filed is Blank",2
                Exit Sub
            End If
        Else
            UpdateMessage "Input File Does Not Exist",2
            Exit Sub
        End If

        'Make Textarea Visible
        document.all.fileContents.style.display = "block"
    End Sub

    Sub CommitInstruction
    'Save Current Instruction to Recipe

        'Check that Instruction Exists
        If strInstruction = Empty Then
            UpdateMessage "Instruction is Blank or Does Not Exist",2
            Exit Sub
        End If

        'Check whether a Recipe Exists
        If objFSO.FileExists("C:\Temp\Temp_Recipe.txt") Then
            Set objRecipe = objFSO.GetFile("C:\Temp\Temp_Recipe.txt")

            'Check the Recipe Contains Instructions
            If objRecipe.size > 0 And strUserConfirmedAction = "" Then

                'Check How User Wants to Interact with Present Recipe - Overwrite or Amend?
                userConfirm = Msgbox("A partial Recipe already exists. Should it be deleted?",35,"How to Proceed?")

                'User Decision: Overwrite (Yes - 6) or Amend (No - 7)
                If userConfirm = 6 Then
                    strUserConfirmedAction = "Overwrite"
                Elseif userConfirm = 7 Then

                    'Request Further User Input
                    userConfirm = Msgbox("Amend the partial Recipe with new Instructions?",33,"How to Proceed?")
                    If userConfirm = 1 Then
                        strUserConfirmedAction = "Amend"
                    Elseif userConfirm = 2 Then
                        'Cancel Operation & Open Temp Folder
                        Msgbox "Delete Current Recipe & Try Again",64,"Operation Cancelled"
                        userConfirm = Empty
                        UpdateMessage "Commit Cancelled by User",2
                        Set objShell = CreateObject("shell.application")
                        objShell.Open("C:\Temp")
                        Exit Sub
                    End If
                Elseif userConfirm = 2 Then
                    UpdateMessage "Commit Cancelled by User",2
                    Exit Sub
                End If
            Elseif strUserConfirmedAction = "" Then
                'If Recipe is Blank, Assume Amending
                strUserConfirmedAction = "Amend"
            End If
        Else
            'Set Field so that Recipe will be Created
            strUserConfirmedAction = "Amend"
        End If

        'Write Instruction to Recipe
        If strUserConfirmedAction = "Overwrite" Then
            'Overwrite Current Recipe & Set to Amend for Further Commits
            Set objFile = objFSO.OpenTextFile("C:\Temp\Temp_Recipe.txt",2,1)
            objFile.WriteLine strInstruction
            objFile.Close
            strUserConfirmedAction = "Amend"
        Elseif strUserConfirmedAction = "Amend" Then
            'Append Current Instruction to Recipe
            Set objFile = objFSO.OpenTextFile("C:\Temp\Temp_Recipe.txt",8,1)
            objFile.WriteLine strInstruction
            objFile.Close
        End If

        'Clear Instruction
        strInstruction = Empty

        'Update Input
        UpdateInput
        UpdateMessage "Instruction Saved and Input Updated",1
    End Sub

    Sub DeleteRecipe
    'User Requests to Delete Current Recipe

        'Ensure User Confirmation is Empty
        strUserDelete = Empty

        'Check that a Recipe Exists
        If objFSO.FileExists("C:\Temp\Temp_Recipe.txt") Then
            'Request User Confirmation
            strUserDelete = Msgbox("Delete Unsaved Recipe Permanently?",17,"Delete File Permanently")
        Else
            UpdateMessage "No Recipe Found - Cannot Delete",2
            Exit Sub
        End If

        'Delete Recipe
        If strUserDelete = 1 Then
            objFSO.DeleteFile("C:\Temp\Temp_Recipe.txt")
            UpdateMessage "Partial Recipe Deleted",1
        Else
            UpdateMessage "User Cancelled Delete Operation",2
        End If
    End Sub

    Sub PreviewRecipe
    'Preview Current Recipe

        'Ensure Values are Empty
        strRecipePreview = Empty

        'Check that a Recipe Exists
        If Not objFSO.FileExists("C:\Temp\Temp_Recipe.txt") Then
            UpdateMessage "Recipe Cannot Be Found",2
            Exit Sub
        Else
            Set objRecipe = objFSO.GetFile("C:\Temp\Temp_Recipe.txt")
            If Not objRecipe.size > 0 Then
                strRecipePreview = "{EMPTY}"
                UpdateMessage "Recipe is Currently Blank",1
            End If
        End If

        'Retrieve & Display Recipe
        Set objRecipe = objFSO.OpenTextFile("C:\Temp\Temp_Recipe.txt",1)
        If strRecipePreview = Empty Then
            strRecipePreview = objRecipe.ReadAll
        End If
        Msgbox strRecipePreview,64,"Recipe Preview:"
    End Sub

    Sub RecordInstructions
    'Continuously Commit Instructions as Each if Run by User

        'Reset Button State & User Input
        strButtonPressed = False
        strUserCommit = Empty

        'Start Recording
        If objRecord = False And strButtonPressed = False Then
            If Not strInstruction = Empty Then
            'Request User Input - Delete or Keep Current Instruction?
                strUserCommit = Msgbox("Commit Current Instruction?",35,"Instruction Already Exists")
                If strUserCommit = 6 Then
                    CommitInstruction
                    'If Commit is Cancelled by User then Don't Continue
                    If Not strInstruction = Empty Then
                        Exit Sub
                    End If
                Elseif strUserCommit = 7 Then
                    strInstruction = Empty
                Elseif strUserCommit = 2 Then
                    Exit Sub
                End If
            End If
            objRecord = True
            strButtonPressed = True
            UpdateMessage "Recording Instructions Initiated",1
            runRecord.innerHTML = "Stop (<span class='quickKey'>d</span>)"
        End If

        'Stop Recording
        If objRecord = True And strButtonPressed = False Then
            If Not strInstruction = Empty Then
            'Request User Input - Delete or Commit Recording?
                strUserCommit = Msgbox("Commit Recorded Instructions?",35,"Recording Ended")
                If strUserCommit = 6 Then
                    CommitInstruction
                    'If Commit is Cancelled by User then Don't Continue
                    If Not strInstruction = Empty Then
                        Exit Sub
                    End If
                Elseif strUserCommit = 7 Then
                    strInstruction = Empty
                Elseif strUserCommit = 2 Then
                    Exit Sub
                End If
            End If
            objRecord = False
            strButtonPressed = True
            UpdateMessage "Recording Instructions Terminated",1
            runRecord.innerHTML = "Recor<span class='quickKey'>d</span>"
        End If
    End Sub

    Sub UpdateInput
    'Refresh the Input After a Commit to Allow Continual Editing

        'Save Original Text on First Commit
        If strOriginalInput = Empty Then
            strOriginalInput = strInput
        End If

        'Update Input
        strInput = strOutput

        'Update GUI
        If objGUIOption = "Type" Then
            userInput.innerHTML = strInput
        Else
            fileContents.innerHTML = strInput
        End If
        expOutput.innerHTML = ""
    End Sub

    Sub Test
        Msgbox(strOutput)
    End Sub
</script>
<style>
    body {
        margin: 0 20px;
        padding: 0;
        font-family: "Segoe UI", Geneva, sans-serif;
        background: #f3f3f3;
        overflow: auto;
    }
    h1 {
        font-size: 15pt;
        text-align: center;
        margin-bottom: 0;
        color: #273754;
    }
    pre {
        line-height: 8px;
        font-family: "Courier New", Courier, monospace, sans-serif;
        background: #ffffff;
        height: 150px;
        overflow: auto;
        padding: 10px;
    }
    button {
        padding: 10px;
        font-size: 16px;
        font-weight: 100;
        color: #fff;
        background: #777d84;
        border: 0;
    }
    button.select {
        padding: 5px 10px;
        font-size: 12px;
        margin: 0 1px;
    }
    button:hover {
        background: #646a70;
    }
    input[type=text] {
        height: 20px;
        width: 72%;
    }
    textarea {
        overflow: auto;
    }
    .error {
        color: #e22b2b;
    }
    .folderInput {
        width: 85%;
        margin: auto;
    }
    .folderSelect {
        margin:0 20px 0 0;
        display: block;
        float: left;
        width: 100px;
    }
    .buttonContainer {
        margin: auto;
        text-align: center;
    }
    input[type=button].featureButton {
        width: 100px;
        font-size: 12px;
        padding: 5px 10px;
    }
    span.quickKey {
        text-decoration: underline;
    }
    #logArea {
        height: 8px;
    }
    #retrieveRAW {
        margin-top: 20px;
        font-weight: bold;
        background: #4a8e0b;
    }
    .right {
        float: right;
    }
</style>
<body>
    <div>
        <H1>Test Regular Expression</H1>
        <p>
            <form id="userInputMethod">
                <span class="option">Free Type Input:</span>
                <input name="selectInputMethod" type="radio" onClick="ChooseTextArea" checked>
                <span class="option">Select File Input:</span>
                <input name="selectInputMethod" type="radio" onClick="ChooseFile">
            </form>
            <textarea name="userInput" rows=10 cols=100></textarea>
            <span id="selectFolder"><input type="text" id="fileInput" size=100><button id="runFolder" onClick="UploadSelectedFile">Submit</button></span>
        </p>
        <p>
            <textarea name="fileContents" rows=10 cols=100></textarea>
        </p>
    </div>
    <div>
        <p>
            Regular Expression to Test:<br>
            <input type="text" id="inputExp" size=100>
        </p>
        <p>
            Replace With:<br>
            <input type="text" id="replaceExp" size=100>
        </p>
    </div>
    <div>
        <button id="runReplace" onClick="GetUserInput('Replace')" accessKey="r"><span class="quickKey">R</span>eplace</button>
        <button id="runReplaceAll" onClick="GetUserInput('ReplaceAll')" accessKey="a">Replace <span class="quickKey">A</span>ll</button>
        <button id="runFind" onClick="GetUserInput('Find')" accessKey="f"><span class="quickKey">F</span>ind</button>
        <span class="right">
            <button id="runCommit" onClick="CommitInstruction" accessKey="c"><span class="quickKey">C</span>ommit</button>
            <button id="runRecord" onClick="RecordInstructions" accessKey="d">Recor<span class="quickKey">d</span></button>
            <button id="runPreview" onClick="PreviewRecipe" accessKey="v">Pre<span class="quickKey">v</span>iew</button>
            <button id="runDelete" onClick="DeleteRecipe">Delete</button>
            <button id="runTest" onClick="Test" accessKey="t"><span class="quickKey">T</span>est</button>
            <button id="runCook" onClick="Test" accessKey="k">Coo<span class="quickKey">k</span></button>
        </span><br><br>
    </div>
    <div>
        <pre id="logArea">Ready to Begin...</pre>
    </div>
    <div>
        <pre id="expOutput"></pre>
    </div>
</body>
</html>

1 个答案:

答案 0 :(得分:2)

Pattern Property documentation关于$模式字符过于简短:

  

$匹配输入的结尾。

有关更详细的说明,请阅读Regular Expression Programming (Scripting)文章(向下滚动到 Flags 段落)。简而言之:

  

标志

     

在JScript正则表达式/abc/gim中,g指定了   全局标志,i指定忽略大小写标志,m指定多行标志。

     

在VBScript中,您可以通过设置等效项来指定这些标志   属性为True

     

...

     

     
      
  • ^匹配\n\r
  • 后的排名   
  • $匹配\n\r之前的位置。
  •   

实际$匹配\n之前的\r LF 之前的位置( CR )。

案例说明

  • 如果输入字段为测试 CR LF 测试 CR LF 测试
    • 和正则表达式模式是 $
    • 替换字段为 @
  • 然后 Replace All操作结果为测试@ CR @ LF 测试@ CR @ LF 测试@

解决方案(通常不是):

  • 使用\b$模式(它不会匹配空行的结尾或行尾与任何尾随空格,包括空格,制表符等。)
  • 替换为字段中使用\r\n模式结尾\n(它不会与不以{{1}结尾的最后一行匹配} CR LF )。

出于调试目的,我使用以下代码存根改进了#147行的HTA代码:

\r\n