Script to do a find with "List lines containing string" option enabled

Script to do a find with "List lines containing string" option enabled

3
NewbieNewbie
3

    Apr 05, 2012#1

    Hi,

    I think I have a simple script request but can't find an answer to it anywhere. Is it even possible?

    I simply want to copy all lines that contain a certain text and paste them into a new document.

    Yes, I know about the script example given that will iterate through each find, copy a line and continue. This works.. but it's soo slow that it's faster for me to do the operation manually, using the "List lines containing string" option.

    Basically, the action I really want to do is this:

    - open find dialog with "List lines containing string" option checked
    - select "Clipboard" button in the dialog that appears listing all lines containing this string
    - paste clipboard text into new document

    Can someone help me with this?? I'd really appreciate it!

    ps: the code I have today is below.. it's just too darn slow on large log files that it's not worth using.

    Code: Select all

    // Start at the beginning of the file
    UltraEdit.activeDocument.top();
    
    // Search string variable used for deletion of lines
    var delString = "text to search for"
    
    // Establish our search string for the loop condition
    UltraEdit.activeDocument.findReplace.find(delString);
    
    // Variable to count found items
    i = 0;
    
    // Start with nothing on the clipboard
    UltraEdit.clearClipboard();
    
    // Loop through the file, count and delete found lines
    while (UltraEdit.activeDocument.isFound())
    {
         // We use an if statement here, because when the above "isFound" is evaluated,
         // the script will use the last Find operation for re-evaluation instead of initiating
         // a new one, causing one extra unintended deletion.
         if (UltraEdit.activeDocument.isFound()) {
              UltraEdit.activeDocument.selectLine();
              UltraEdit.activeDocument.copyAppend();
              i++;
         }
         
         UltraEdit.activeDocument.findReplace.find(delString);
    }
    
    if (i == 0){
         UltraEdit.messageBox("No occurrences of \"" + delString + "\" found in this file.");
    } else {
         // Create a new file for the report
         UltraEdit.newFile();
         UltraEdit.activeDocument.paste();
         UltraEdit.activeDocument.top();
         UltraEdit.activeDocument.write(i + " lines containing \"" + delString + "\" were found in this file.\r\n\r\n");
    } 
    eu-clipboard.jpg (127.39KiB)
    find results - clipboard
    ue-find.jpg (51.76KiB)
    find dialog

    6,603548
    Grand MasterGrand Master
    6,603548

      Apr 05, 2012#2

      The help page Scripting commands as well as the tag group UE/UES Script Commands in tag list view list all UltraEdit scripting commands and properties. Additionally supported are only the Javascript core objects, functions and properties.

      There is no property to run a find with option (property) list lines containing string from within a script.

      There is no command to do a dialog button click or execute the command of a dialog. Dialogs are for user interactions and therefore no command is supported which results in opening a dialog or executing a dialog function. A dialog is a completely different object (class in C++) than the document object. And in scripting environment only 3 objects are supported.

      Therefore what you want can't be done with an UltraEdit script.

      You can maybe use AutoHotkey with an appropriate script because this tool simulates user actions.


      What about the opposite? Instead of creating a list of interesting lines, copy the entire contents of a file to a new file and use a regular expression replace all to delete all lines not containing the string of interest. See How to delete all lines NOT containing specific word or string or expression?


      Another method is to use Find in Files command on just a single file with results written to a document window.

      Code: Select all

      UltraEdit.ueReOn();
      UltraEdit.frInFiles.regExp=false;
      UltraEdit.frInFiles.filesToSearch=0;
      UltraEdit.frInFiles.matchCase=false;
      UltraEdit.frInFiles.matchWord=false;
      UltraEdit.frInFiles.searchSubs=false;
      UltraEdit.frInFiles.directoryStart="";
      UltraEdit.frInFiles.useEncoding=false;
      UltraEdit.frInFiles.reverseSearch=false;
      UltraEdit.frInFiles.useOutputWindow=false;
      UltraEdit.frInFiles.searchInFilesTypes=UltraEdit.activeDocument.path;
      UltraEdit.frInFiles.displayLinesDoNotMatch=false;
      UltraEdit.frInFiles.ignoreHiddenSubs=false;
      var sSearchString = UltraEdit.getString("List lines containing:",1);
      UltraEdit.frInFiles.find("sSearchString");
      UltraEdit.activeDocument.top();
      The code as posted here runs a Find in Files on active file only for an ANSI string entered on script execution by the script user. This code does not work for new unsaved files because there is no file.

      UltraEdit.activeDocument.encoding could be evaluated to decide using the Find in Files propertiesuseEncoding (boolean) and encoding (integer) to run the Find in Files with correct encoded search string. But I suppose for your log files such an additional code is not necessary.

      The results file created is a Unicode file which you could next covert to ASCII/ANSI. Depending on Advanced - Configuration - Search - Set Find Output Format the results file could contain more than just the found lines. You can use the configuration settings and/or regular expression replace all commands to remove all not needed additional information and get the output you would like to see.

      Last take a look on Find strings with a regular expression and output them to new file,

      3
      NewbieNewbie
      3

        Apr 05, 2012#3

        Thanks for the excellent suggestions!

        I had wondered about the find in files but then ran into that same question with unsaved files.. but even still both suggestions are more than enough to go off of.

        I also appreciate the link to the scripting commands. I was looking for exactly that (btw - not that easy to find; maybe I wasn't looking in the right place though).

        thanks again,
        joe

          Apr 05, 2012#4

          Almost there.. the replace option should work great for me. But, I'm afraid my Perl regular expression knowledge stinks!

          Anyone know what I'm missing in the replace() function call to just have it remove the line? Right now, it just leaves the empty line.

          -- this works but doesn't delete the line (just clears it) --

          Code: Select all

          UltraEdit.activeDocument.findReplace.replace("^(?:(?!Text to keep).)*$", "");
          
          -- I imagine I need something like this - but it doesn't delete anything --

          Code: Select all

          UltraEdit.activeDocument.findReplace.replace("^(?:(?!Text to keep).)*$\r\n", "");
          
          Any ideas?

          -- current code so far --

          Code: Select all

          // Start with nothing on the clipboard
          UltraEdit.clearClipboard();
          
          // select all
          UltraEdit.activeDocument.selectAll();
          
          // copy to clipboard
          UltraEdit.activeDocument.copy();
          
          // new doc
          UltraEdit.newFile();
          
          // paste
          UltraEdit.activeDocument.paste();
          
          // move cursor to top
          UltraEdit.activeDocument.top();
          
          // Define the parameters for all regular expression replaces
          // done with the UltraEdit regular expression engine.
          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;
          UltraEdit.activeDocument.findReplace.preserveCase=false;
          UltraEdit.activeDocument.findReplace.replaceAll=true;
          UltraEdit.activeDocument.findReplace.replaceInAllOpen=false;
          
          // Establish our search string for the loop condition
          UltraEdit.activeDocument.findReplace.replace("^(?:(?!Text to keep).)*$", "");
          

          6,603548
          Grand MasterGrand Master
          6,603548

            Apr 06, 2012#5

            First, your script does not contain the command UltraEdit.perlReOn(); to select the Perl regular expression for find/replaces during script execution.


            Second, UltraEdit.clearClipboard(); at top of the script is useless, except you plan to run the script also on an empty file.


            Third, I suggest to insert at top of the script instead of the UltraEdit.clearClipboard(); command the command UltraEdit.selectClipboard(9); to use user clipboard 9 instead of default Windows clipboard. It is always good that a script or macro does not destroy contents of Windows clipboard used system wide. Additionally after the paste command you should use the commands

            Code: Select all

            UltraEdit.clearClipboard();    // free memory
            UltraEdit.selectClipboard(0);  // select Windows clipboard
            You can make it more complicated if you use often user clipboards by evluating UltraEdit.clipboardIdx property to not use the Windows clipboard and the active user clipboard and restore the clipboard active on script start. I avoid that by simply using manually the user clipboards from user clipboard 1 up to x and use in macros and scripts the user clipboards 9 down to y.


            Fourth, the search string should be:

            UltraEdit.activeDocument.findReplace.replace("^(?:(?!Text to keep).)*$\\r\\n", "");

            The backslash character is also an escape character in Javascript strings. So if you use just just \r\n, the Javascript interpreter translates this string to the byte sequence 0x0D 0x0A and this 2 bytes are passed to the Perl regular expression engine instead of the string \r\n. That should not make a difference, but it makes a difference for some unknown reason. Every backslash in a Perl regular expression search/replace string must be escaped with an additional backslash in scripts.


            Fifth, keep in mind that Text to keep should not contain any Perl regular expression character. If you plan to replace this text dynamically by a user entered string, you need to escape all Perl regular expression characters in the user entered string by inserting a backslash before you can use this string in the search string.


            Sixth, you have hopefully selected DOS for configuration setting Default file type for new files and have configuration setting On paste convert line endings to destination type (Unix/Mac/DOS) also enabled. Otherwise it could happen that the new file does not contain DOS line terminators and therefore the Perl regular expression replace does not delete any line because no line ends with carriage return plus linefeed.


            Seventh, immediately after paste command insert the commands.

            Code: Select all

            if (UltraEdit.activeDocument.isColNumGt(1)) {
               UltraEdit.activeDocument.insertLine();
               if (UltraEdit.activeDocument.isColNumGt(1)) {
                  UltraEdit.activeDocument.deleteToStartOfLine();
               }
            }
            That makes sure that last line in the new file has always a line termination. This is important because if the last line has no line termination and does not contain the string of interest, it would not be deleted by the regular expression replace because of the missing line termination.


            And last, all my scripts doing something on an active file are enclosed in

            Code: Select all

            if(UltraEdit.document.length > 0) {
               // script code
            }
            Why? Well, you can assign a hotkey to a script added to script list. That makes it easily possible to execute the script by mistake in UltraEdit while no file is open at all. In this case the script uses object UltraEdit.activeDocument which does not exist because there is no active document. That's not good. This is also important when running a script from command line with a file also specified on a command line. If there was made a mistake and the file to run the script on does not exist, the script must fail. I would not be surprised if UltraEdit crashes when running scripting commands using a NULL object.