Community
    • Login

    Search a number grater than

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    9 Posts 5 Posters 2.7k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Vitor FesselV
      Vitor Fessel
      last edited by

      how to perform a search in a txt file, for a number greater than or equal to 25 of a specific variable, using Find?
      Example:
      Variable: "Length: "
      Search: “>= 25”
      How to set up search in Find? Which options should I use?

      Alan KilbornA PeterJonesP Neil SchipperN 3 Replies Last reply Reply Quote 0
      • Alan KilbornA
        Alan Kilborn @Vitor Fessel
        last edited by Alan Kilborn

        @Vitor-Fessel

        You won’t like the answer; it isn’t trivial.

        Here’s one possible way:

        Find: \b(\d{3,}|2[5-9]|[3-9]\d)\b
        Search mode: Regular expression

        You didn’t say exactly how the Length: part comes into it, but if it is like Length:35 then just put Length: at the front of the expression.

        However, this is probably going to end up where you are doing json or xml or some such, in which case, using raw Notepad++ find (or replace) may not be the route in which to go.

        1 Reply Last reply Reply Quote 1
        • PeterJonesP
          PeterJones @Vitor Fessel
          last edited by PeterJones

          @Vitor-Fessel ,

          Notepad++'s search doesn’t do math (including numeric value greater than): numbers are just characters to the search/replace engine.

          If Alan’s regex (regular expression search) isn’t sufficient for you, we’ve got a FAQ that explains how to use a plugin and some programming (on your part) to do the math.

          Alan KilbornA 1 Reply Last reply Reply Quote 2
          • Alan KilbornA
            Alan Kilborn @PeterJones
            last edited by

            @PeterJones said in Search a number grater than:

            we’ve got a FAQ that explains how to use a plugin and some programming (on your part) to do the math.

            The FAQ only shows techniques for replacing, and OP only mentioned finding … thus far. For just finding and doing “real math”, we don’t have a canned solution / good examples for that.

            PeterJonesP 1 Reply Last reply Reply Quote 1
            • Neil SchipperN
              Neil Schipper @Vitor Fessel
              last edited by Neil Schipper

              @Vitor-Fessel

              If you wish to include leading 0’s in the match, or if you wish to tolerate non-digits adjacent to the digits on either side, you could use
              find expression 0*(?:[3-9]\d|2[5-9])\d*

              It implements this logic:

              <optional leading zeros>
              (
                <a digit in range 3-9 followed by at least one digit>
                  or
                <a 2 followed by a digit in range 5-9>
              )
              <optional trailing digits>
              

              It can be tested against:

              00004
              00004z
              x00004
              000014
              000024
              000025
              000026
              v000026
              000026b
              0090026
              0090026054875f
              
              1 Reply Last reply Reply Quote 1
              • PeterJonesP
                PeterJones @Alan Kilborn
                last edited by PeterJones

                @Alan-Kilborn said in Search a number grater than:

                thus far.

                Challenge accepted.

                # encoding=utf-8
                """https://community.notepad-plus-plus.org/post/86443
                
                Bookmark any line that starts with an integer greater than
                or equal to 25.
                
                """
                from Npp import editor, notepad, MENUCOMMAND
                import re  # to be able to use Python's regular expression library
                
                def custom_match_func(m):
                    i = int(m.group(0))
                    if i >= 25:
                        editor.setSel( m.start(0), m.end(0) )
                        notepad.menuCommand(MENUCOMMAND.SEARCH_TOGGLE_BOOKMARK)
                        # really should check bookmark status first, and have it
                        # only toggle if it's not already bookmarked
                        # but that goes beyond the scope of this FAQ
                
                # notepad.menuCommand(MENUCOMMAND.SEARCH_CLEAR_BOOKMARKS) # optionally clear bookmarks before this search
                editor.research(r'^\b\d+\b', custom_match_func)
                
                """
                Here is example data to test it on:
                1. Here
                Here is 25
                25 here         This line should match
                Yep
                99999 is OK     So should this one
                
                """
                

                This can be easily customized in the editor.research() line to look for r'Length: (\d+) and have the callback use group index 1 instead of 0 throughout, to meet @Vitor-Fessel’s requirements.

                Alan KilbornA 1 Reply Last reply Reply Quote 2
                • Alan KilbornA
                  Alan Kilborn @PeterJones
                  last edited by

                  @PeterJones

                  Minor point but by “thus far” I meant that the OP hadn’t expressed any “replacing” desire (only finding), not that the “math faq” entry hasn’t shown how to do anything but replaces.

                  The bookmarking approach is “okay” but it might rub someone that wants a step-by-step find or a “find all” the wrong way.

                  Find-all is difficult to implement because scripts can’t really add output to the Search results window. :-(

                  However, step-by-step find, aka “Find Next” is reasonable; here’s my take on it; every time it is run it finds the next value that meets the spec:

                  # -*- coding: utf-8 -*-
                  
                  # references:
                  #  https://community.notepad-plus-plus.org/topic/24481
                  
                  from Npp import *
                  
                  def custom_match_func(m):
                      if custom_match_func.stop: return
                      i = int(m.group(0))
                      if i >= 25:
                          editor.setSel(m.start(0), m.end(0))
                          custom_match_func.stop = True
                  
                  custom_match_func.stop = False
                  editor.research(r'\b\d+\b', custom_match_func, 0, editor.getCurrentPos())
                  
                  PeterJonesP Mark OlsonM 2 Replies Last reply Reply Quote 2
                  • Alan KilbornA Alan Kilborn referenced this topic on
                  • PeterJonesP
                    PeterJones @Alan Kilborn
                    last edited by

                    @Alan-Kilborn said in Search a number grater than:

                    @PeterJones

                    Minor point but by “thus far” I meant that the OP hadn’t expressed any “replacing” desire (only finding), not that the “math faq” entry hasn’t shown how to do anything but replaces.

                    Oh, okay. Well, it was still actually a deficiency in the FAQ, so… ;-)

                    The bookmarking approach is “okay” but it might rub someone that wants a step-by-step find or a “find all” the wrong way.

                    I agree. Doing the bookmark was just my compromise between find-next and find-all, because “bookmark all” would allow a user to use the next/previous bookmark to then navigate between results.

                    Find-all is difficult to implement because scripts can’t really add output to the Search results window. :-(

                    My thought for a Find All would be to do a multi-selection to put all the matches in a single selection, though that’s probably not actually what would be natural, either.

                    However, step-by-step find, aka “Find Next” is reasonable; here’s my take on it; every time it is run it finds the next value that meets the spec:

                    Interesting that you chose to do a toggle. Why not just set the maxCount parameter of editor.research to 1? (… some experimenting later…) Oh, right, because not every editor.research match also matches the internal math restriction, so in my example file, since the first number that matches wasn’t big enough, the selection didn’t move forward, which meant that when I ran it a second time, it started from the old caret not the new caret, and got in an infinite loop of finding the first number but not selecting it; that should have been more obvious to me than it was.

                    1 Reply Last reply Reply Quote 0
                    • Mark OlsonM
                      Mark Olson @Alan Kilborn
                      last edited by

                      @Alan-Kilborn
                      With your script as inspiration, I made one that has a different custom search func for each file, allows the user to set the search func with selected text, and the user can choose whether or not to bookmark lines.
                      63ddf9b8-22a9-411a-8448-33a055dcf3fa-image.png

                      # -*- coding: utf-8 -*-
                      
                      # references:
                      #  https://community.notepad-plus-plus.org/topic/24481
                      from Npp import *
                      import operator
                      import re
                      
                      # Too lazy to parse config files; just modify these global variables instead
                      BOOKMARK_LINES = True
                      
                      class FBOLTN:
                          def __init__(self):
                              self.set_comparator()
                              
                          def set_comparator(self):
                              comparator_regex = re.compile("([><]=?|=)(-?\d+)")
                              sel = editor.getSelText()
                              mtch = comparator_regex.search(sel)
                              if mtch: # user is selecting a new comparator
                                  compstr, numstr = mtch.groups()
                                  num = int(numstr)
                              else:
                                  if hasattr(self, 'comparator'):
                                      return # only override current comparator with valid selection
                                  # default is what the OP wanted
                                  compstr = '>='
                                  num = 25
                              self.compstr = compstr
                              self.num = num
                              def comparator(other_num):
                                  fun = {
                                      '>': operator.gt,
                                      '<': operator.lt,
                                      '=': operator.eq,
                                      '>=': operator.ge,
                                      '<=': operator.le,
                                  }[compstr]
                                  return fun(other_num, num)
                              self.comparator = comparator
                      
                          def custom_match_func(self, m):
                              if self.stop: return
                              i = int(m.group(0))
                              start, end = m.start(0), m.end(0)
                              if self.comparator(i):
                                  editor.setSel(start, end)
                                  if BOOKMARK_LINES:
                                      notepad.menuCommand(MENUCOMMAND.SEARCH_TOGGLE_BOOKMARK)
                                  self.stop = True
                      
                          def search(self):
                              self.stop = False
                              editor.research(r'(?<!\w)-?\d+\b', self.custom_match_func, 0, editor.getCurrentPos())
                          
                      if __name__ == '__main__':
                          try:
                              fboltns
                          except NameError:
                              fboltns = {}
                          cur_fname = notepad.getCurrentFilename()
                          if not fboltns.get(cur_fname):
                              fboltns[cur_fname] = FBOLTN()
                          fboltn = fboltns[cur_fname]
                          fboltn.set_comparator()
                          fboltn.search()
                      
                      1 Reply Last reply Reply Quote 3
                      • Mark OlsonM Mark Olson referenced this topic on
                      • First post
                        Last post
                      The Community of users of the Notepad++ text editor.
                      Powered by NodeBB | Contributors