Find/replace script with increasing numbers which are reset at new line

Find/replace script with increasing numbers which are reset at new line

2
NewbieNewbie
2

    May 29, 2021#1

    I am trying to write a find/replace script with a number appended to each replacement. The number must increase but also be reset at the start of each line.
     
    For example, in the following paragraph I would like %@ to be replaced by {TOKENx} where x is an increasing number starting at 0. But x must be reset to 0 at the start of each line:
     
    The %@ went to the %@ and then walked home.
    Later, the %@ found his wallet.
    The man was old and grey.
    She didn’t see the %@ until it was too late. %@. %@.
     The %@ was very brave!

    The output should be:
     
    The {TOKEN0} went to the {TOKEN1} and then walked home.
    Later, the {TOKEN0} found his wallet.
    The man was old and grey.
    She didn’t see the {TOKEN0} until it was too late. {TOKEN1}. {TOKEN2}.
     The {TOKEN0} was very brave!

    I am not sure if this is relevant but I am using UltraEdit for Mac. 

    Any help would be greatly appreciated. 😊

    6,686585
    Grand MasterGrand Master
    6,686585

      May 30, 2021#2

      The first version can be used on any file with any file size as long as the lines end with a line-feed (DOS/UNIX). It replaces the token placeholder strings one after the other in active file. So there is an undo record for each token placeholder string.

      Code: Select all

      if (UltraEdit.document.length > 0)  // Is any file opened?
      {
         // Define environment for this script.
         UltraEdit.insertMode();
         if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
         else if (typeof(UltraEdit.activeDocument.columnModeOff) == "function") UltraEdit.activeDocument.columnModeOff();
      
         // Move caret to top of the active file.
         UltraEdit.activeDocument.top();
      
         // Define the parameters for the two finds.
         UltraEdit.ueReOn();
         UltraEdit.activeDocument.findReplace.mode=0;
         UltraEdit.activeDocument.findReplace.matchCase=true;
         UltraEdit.activeDocument.findReplace.matchWord=false;
         UltraEdit.activeDocument.findReplace.regExp=false;
         UltraEdit.activeDocument.findReplace.searchDown=true;
         if (typeof(UltraEdit.activeDocument.findReplace.searchInColumn) == "boolean") {
            UltraEdit.activeDocument.findReplace.searchInColumn=false;
         }
      
         // Define the counter variables.
         var nLineCount=0;
         var nTokenCount=0;
         var nReplaceCount=0;
      
         // In main loop search for next occurrence of the token placeholder
         // with using a case-sensitive, non-regular expression find.
         while (UltraEdit.activeDocument.findReplace.find("%@"))
         {
            // Replace token placeholder by the token with the count number 0.
      //      UltraEdit.activeDocument.write("{TOKEN" + nTokenCount.toString(10) + "}");
            UltraEdit.activeDocument.write("{TOKEN0}");
            // Increment the line and replace counters.
            nLineCount++;
            nReplaceCount++;
      
            // The inner loop searches for either token placeholder or a line-feed
            // using a case-sensitive UltraEdit regular expression find.
            UltraEdit.activeDocument.findReplace.regExp=true;
            while (UltraEdit.activeDocument.findReplace.find("^{^%@^}^{^n^}"))
            {
               // Is the found string not a line-feed?
               if (UltraEdit.activeDocument.selection != "\n")
               {
                  // Replace the token placeholder by the token string with
                  // an incremented number and increment the replace counter.
                  nTokenCount++;
                  UltraEdit.activeDocument.write("{TOKEN" + nTokenCount.toString(10) + "}");
                  nReplaceCount++;
               }
               else
               {
                  // End of line found resulting in breaking the inner loop
                  // after turning off regular expression find and resetting
                  // the token counter to zero.
                  UltraEdit.activeDocument.findReplace.regExp=false;
                  nTokenCount=0;
                  break;
               }
            }
         }
      
         // Move caret again to top of the active file.
         UltraEdit.activeDocument.top();
         // Turn off displaying script execution status in output window and clear
         // the output window before writing to the output window a short summary
         // information and show the output window on not visible at the moment.
         UltraEdit.outputWindow.showStatus=false;
         UltraEdit.outputWindow.clear();
         if (nReplaceCount)
         {
            UltraEdit.outputWindow.write("Replaced " + nReplaceCount.toString(10) +
            " token" + ((nReplaceCount != 1) ? "s" : "") + " in " + nLineCount.toString(10) +
            " line" + ((nLineCount != 1) ? "s." : "."));
         }
         else
         {
            UltraEdit.outputWindow.write("No token found to replace!");
         }
         if (UltraEdit.outputWindow.visible == false)
         {
            UltraEdit.outputWindow.showWindow(true);
         }
      }
      
      The second version loads a line with a token placeholder string into memory of script interpreter, replaces all the token placeholders strings in this line in memory and writes the updated line back to the file. This is done for each line with a token placeholder string. So this second version produces less undo records as line changes are recorded and not each placeholder replacement separately.

      Code: Select all

      if (UltraEdit.document.length > 0)  // Is any file opened?
      {
         // Define environment for this script.
         UltraEdit.insertMode();
         if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
         else if (typeof(UltraEdit.activeDocument.columnModeOff) == "function") UltraEdit.activeDocument.columnModeOff();
      
         // Move caret to top of the active file.
         UltraEdit.activeDocument.top();
      
         // Define the parameters for find in the loop.
         UltraEdit.perlReOn();
         UltraEdit.activeDocument.findReplace.mode=0;
         UltraEdit.activeDocument.findReplace.matchCase=true;
         UltraEdit.activeDocument.findReplace.matchWord=false;
         UltraEdit.activeDocument.findReplace.regExp=true;
         UltraEdit.activeDocument.findReplace.searchDown=true;
         if (typeof(UltraEdit.activeDocument.findReplace.searchInColumn) == "boolean") {
            UltraEdit.activeDocument.findReplace.searchInColumn=false;
         }
      
         // Define the counter variables.
         var nLineCount=0;
         var nTokenCount=0;
         var nReplaceCount=0;
      
         // In main loop search for next line with the token placeholder
         // with using a case-sensitive, Perl regular expression find.
         while (UltraEdit.activeDocument.findReplace.find("%@.*$"))
         {
            // Load the selected line beginning with first occurrence
            // of the placeholder string into a string variable.
            var sTokenLine = UltraEdit.activeDocument.selection;
            // Replace each token placeholder in this string by the tokens
            // with the number incremented on each found token placeholder.
            do
            {
               sTokenLine = sTokenLine.replace("%@","{TOKEN" + nTokenCount.toString(10) + "}");
               nReplaceCount++;
               nTokenCount++;
            }
            while (sTokenLine.indexOf("%@") > 0);
            // Replace the select line in file by updated line, increment the line
            // counter and reset the token counter to 0 for the next token line.
            UltraEdit.activeDocument.write(sTokenLine);
            nLineCount++;
            nTokenCount=0;
         }
      
         // Move caret again to top of the active file.
         UltraEdit.activeDocument.top();
         // Turn off displaying script execution status in output window and clear
         // the output window before writing to the output window a short summary
         // information and show the output window on not visible at the moment.
         UltraEdit.outputWindow.showStatus=false;
         UltraEdit.outputWindow.clear();
         if (nReplaceCount)
         {
            UltraEdit.outputWindow.write("Replaced " + nReplaceCount.toString(10) +
            " token" + ((nReplaceCount != 1) ? "s" : "") + " in " + nLineCount.toString(10) +
            " line" + ((nLineCount != 1) ? "s." : "."));
         }
         else
         {
            UltraEdit.outputWindow.write("No token found to replace!");
         }
         if (UltraEdit.outputWindow.visible == false)
         {
            UltraEdit.outputWindow.showWindow(true);
         }
      }
      
      The third version loads the entire file content into memory of script interpreter, copies the file content in memory with replacing each occurrence of a token placeholder string by the token string with the incremented number, and finally overwrites the entire file content with the updated file content. This third version can be used only for small files with not more than about 20 MB which can be loaded twice into memory of script interpreter. The advantage is that only one undo record is recorded. The disadvantage is that all lines are marked as changed even if nothing changed on a line.

      Code: Select all

      if (UltraEdit.document.length > 0)  // Is any file opened?
      {
         // Define environment for this script.
         UltraEdit.insertMode();
         if (typeof(UltraEdit.columnModeOff) == "function") UltraEdit.columnModeOff();
         else if (typeof(UltraEdit.activeDocument.columnModeOff) == "function") UltraEdit.activeDocument.columnModeOff();
      
         // Define the counter variables.
         var nLineCount=0;
         var nTokenCount=0;
         var nReplaceCount=0;
      
         // Select the entire file content and load the file content
         // into a string variable if active file is not empty,
         UltraEdit.activeDocument.selectAll();
         if (UltraEdit.activeDocument.isSel())
         {
            var sFileContent = UltraEdit.activeDocument.selection;
            var sUpdatedContent = "";
            var nFoundPosition;
            var nStartPosition = 0;
            var nLineFeedPosition = 0;
      
            while (true)
            {
               // Find the next occurrence of the token placeholder string.
               nFoundPosition = sFileContent.indexOf("%@",nStartPosition);
               // Is there no more token placeholder string?
               if (nFoundPosition < 0)
               {
                  // Append the remaining file content to the
                  // updated file content and break the loop.
                  sUpdatedContent += sFileContent.substring(nStartPosition);
                  break;
               }
               // Is this placeholder found on a different line?
               if (nFoundPosition > nLineFeedPosition)
               {
                  // Reset the token counter to 0, increment the line counter,
                  // search for next line-feed in file content and if there is
                  // no more line-feed, interpret end of file as end of line.
                  nTokenCount=0;
                  nLineCount++;
                  nLineFeedPosition = sFileContent.indexOf("\n",nFoundPosition+2);
                  if (nLineFeedPosition < 0) nLineFeedPosition = sFileContent.length;
               }
               // Append everything between previous occurrence of token placeholder
               // string and this token placeholder string to the updated file cotent
               // and append the token string with current token number.
               sUpdatedContent += sFileContent.substring(nStartPosition,nFoundPosition) +
                                  "{TOKEN" + nTokenCount.toString(10) + "}";
               // Set the start position for next token placeholder string search
               // after the current token placeholder string in file content string.
               nStartPosition = nFoundPosition + 2;
               // Increment the replace counter and the token counter.
               nReplaceCount++;
               nTokenCount++;
            }
      
            // Replace the entire and still selected file content by the
            // updated file content with the tokens with incremented numbers.
            if (nReplaceCount) UltraEdit.activeDocument.write(sUpdatedContent);
         }
      
         // Move caret to top of the active file which also cancels the selection.
         UltraEdit.activeDocument.top();
         // Turn off displaying script execution status in output window and clear
         // the output window before writing to the output window a short summary
         // information and show the output window on not visible at the moment.
         UltraEdit.outputWindow.showStatus=false;
         UltraEdit.outputWindow.clear();
         if (nReplaceCount)
         {
            UltraEdit.outputWindow.write("Replaced " + nReplaceCount.toString(10) +
            " token" + ((nReplaceCount != 1) ? "s" : "") + " in " + nLineCount.toString(10) +
            " line" + ((nLineCount != 1) ? "s." : "."));
         }
         else
         {
            UltraEdit.outputWindow.write("No token found to replace!");
         }
         if (UltraEdit.outputWindow.visible == false)
         {
            UltraEdit.outputWindow.showWindow(true);
         }
      }
      
      All three versions open the output window on finishing with showing a short summary information.
      Best regards from an UC/UE/UES for Windows user from Austria

      2
      NewbieNewbie
      2

        May 31, 2021#3

        Hi Mofi,

        Thanks very much for the detailed scripts!

        I am having trouble running them though. I have my document open but when I run one of your scripts nothing seems to happen. I right-click on the script in the Script List pane and choose Run. Then an alert box appears briefly with the title Cancel operation before disappearing almost instantly. The output window you mentioned doesn't appear at the end. 

        I opened the output window manually as you suggested and the script was failing on line 5:

        Code: Select all

        UltraEdit.columnModeOff();
        So I deleted this line and the script worked, replacing where necessary, but would not come out of the while loop for some reason. I ended up having to quit the application to stop the infinite loop which meant the changes to the document were not saved. 

        So I ended up adding:

        Code: Select all

        UltraEdit.saveAs(UltraEdit.activeDocument.path);
        at the end of the while loop so that when I had to quit, the changes were at least saved. A bit hacky but it got the job done!

        Thanks again for your time and effort in providing these scripts, you saved me hours of work. 😊

        6,686585
        Grand MasterGrand Master
        6,686585

          Jun 02, 2021#4

          I don't understand why the first script most likely used by you runs into an endless loop. That can happen only if the command

          Code: Select all

          UltraEdit.activeDocument.findReplace.find("%@")
          does not return false on not finding the string anymore in the file. This script command is implemented perhaps different on UEX and for that reason the loop needs to be rewritten to something like:

          Code: Select all

             while (true)
             {
                UltraEdit.activeDocument.findReplace.find("%@");
                if (UltraEdit.activeDocument.isNotFound()) break;
                // The other commands.
             }
          
          However, it should be always possible to press the Cancel button to break script execution. It should be never needed to kill UEX by the operating system.

          I asked IDM support by email regarding to scripting command UltraEdit.columnModeOff() and got the information that in UltraEdit for Mac the command is UltraEdit.activeDocument.columnModeOff(). That difference between UltraEdit for Windows and UltraEdit for Linux/Mac is easy to handle by code once knowing it. I updated the three scripts in my first post with two IF conditions to handle this scripting command difference. I could test of course only the Windows version (first IF condition is true).
          Best regards from an UC/UE/UES for Windows user from Austria