Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Replace routine
#1
Have you guys noticed that "wrap" on searches like Notepad only work when a line-break in not encountered? That makes sense, I guess, but what if you wanted to ignore those line-breaks and find what you are looking for, anyway?

Pete is
tremendous but
Steve is just amazing.

So search that for Pete is tremendous. No go in most html editors or Notepad. I don't Word or OpenOffice, anymore, so I don't know if they would find the search or not.

Anyway, I got a little burned out with trying a strict math model to accomplish this, so I combined a math and string replacement method to get the job done. It's super fast, but it has a drawback in that the file being searched cannot contain 3 substitute string characters I used to handle the line-break situation. Chr$(1), Chr$(3), and Chr$(4). Us SCREEN 0 card programmers are screwed for diamonds and hearts!

So I'm curious if anyone has coded this and figured out a pure math method? 

Now the routine itself is actually very useful for html files, which often contain text broken up on different lines. I coded it to preserve line-breaks. I have not, and may not go to the extent of perfect line-break mirroring, as that would require checking the for the nearest space in the replacement term instead of stacking the line-breaks onto the end. Yes, it can handle search and replace over multiple line-breaks. For instance...

Pete is
tremendous but

Steve is just amazing.

Search for: Pete is tremendous
Replace with: Pete is TREMENDOUS

The results with my routine would be...

Pete is TREMENDOUS

but
Steve is just amazing.

instead of...

Pete is
TREMENDOUS but

Steve is just amazing.
----------------------------------------
So not an exact mirror, but it does get the job, essentially, done.

Here's the code. It won't change any of your files, or make any new ones. It just loads the edited content to your clipboard and opens Notepad. You can paste it in to view it. Just pick a text file (.bas, .txt, .html, etc.), or make a test file, to try it out.

Code: (Select All)
Width 80, 25: _Font 16: _ScreenMove _Middle
Print "Opening file dialog..."
target$ = _OpenFileDialog$("Open a file to to be searched:", "", "*.*", "", 0)
If target$ = "" Then System
Print: Print "This routine copies the contents of the file to your clipboard.": Print
search:
If _FileExists(target$) Then Else Print "Error, file not found: " + target$: End
Dim As Integer seed, q, j, k, i1, i3, i4
Open target$ For Binary As #1
a$ = Space$(LOF(1))
Get #1, , a$
Close #1
Line Input "Search for:  ", find$: Print
Line Input "Replace with: ", replace$: Print
If find$ <> replace$ Then
    a2$ = a$: c = 0
    Do ' Strip out line-breaks and substitute space for a single line-break.
        q = InStr(seed, a$, Chr$(13) + Chr$(10))
        If q Then
            If Mid$(a$, q + 2, 2) = Chr$(13) + Chr$(10) Or Mid$(a$, q + 2) = "" Then
                sp$ = "": sp2$ = ""
                For j = 0 To Len(a2$) Step 2
                    If Mid$(a2$, q + j, 2) <> Chr$(13) + Chr$(10) Then Exit For
                Next
                If j Then lb = lb + 1: ReDim _Preserve line_break(lb) As Integer: line_break(lb) = j / 2
            Else
                sp$ = " ": sp2$ = Chr$(1): If j Then sp2$ = Chr$(3)
                j = 0
            End If
            a$ = Mid$(a$, 1, q - 1) + sp$ + Mid$(a$, q + 2)
            a2$ = Mid$(a2$, 1, q - 1) + sp2$ + Mid$(a2$, q + 2)
            seed = q
        Else
            Exit Do
        End If
        c = c + 1: If c > 1000 Then Print "Oops. We went over 1000 loops without completing the routine.": End ' For beta version this prevents an endless loop for any unhandled condition.
    Loop
    seed = 1
    Do ' Find and Replace.
        q = InStr(seed, LCase$(a$), LCase$(find$))
        If q And Len(find$) <> 0 Then
            Mid$(a2$, q, 1) = Chr$(4)
            seed = q + Len(find$)
        Else
            Exit Do
        End If
    Loop
    j = 0: a$ = "" ' Reconstruct.
    Do
        i1 = InStr(a2$, Chr$(1))
        i3 = InStr(a2$, Chr$(3))
        i4 = InStr(a2$, Chr$(4))
        While -1
            If i1 Then
                If i1 < i3 Or i3 = 0 Then
                    If i1 < i4 Or i4 = 0 Then
                        q = i1
                        x$ = Chr$(13) + Chr$(10)
                        GoSub assemble
                        Exit While
                    End If
                End If
            End If
            If i3 Then
                If i3 < i1 Or i1 = 0 Then
                    If i3 < i4 Or i4 = 0 Then
                        q = i3
                        j = j + 1: x$ = ""
                        For k = 1 To line_break(j): x$ = x$ + Chr$(13) + Chr$(10): Next
                        GoSub assemble
                        Exit While
                    End If
                End If
            End If
            If i4 Then
                If i4 < i1 Or i1 = 0 Then
                    If i4 < i3 Or i3 = 0 Then
                        x$ = replace$
                        q = i4
                        GoSub assemble
                        x$ = Mid$(a2$, 1, Len(find$))
                        For i = 1 To Len(find$)
                            Select Case Mid$(a2$, i, 1)
                                Case Chr$(1)
                                    lb$ = Chr$(13) + Chr$(10)
                                Case Chr$(3)
                                    j = j + 1: x$ = ""
                                    For k = 1 To line_break(j): lb$ = lb$ + Chr$(13) + Chr$(10): Next
                            End Select
                        Next
                        a$ = a$ + lb$: lb$ = ""
                        q = Len(find$)
                        If Mid$(a2$, q, 1) = " " And Right$(a$, 2) = Chr$(13) + Chr$(10) Then q = q + 1 ' Remove leading space.
                        a2$ = Mid$(a2$, q)
                        Exit While
                    End If
                End If
            End If
            a$ = a$ + a2$: a2$ = "": Exit Do ' End of file.
            Exit While
        Wend
    Loop
End If
Print "Finished. Do a Notepad paste to view results. (Opening Notepad...)": Print
Print: Print "[Enter] Run  [Tab] Search this file again.  [Esc] Quit"
Shell _DontWait _Hide "start notepad"
_Clipboard$ = a$
Sleep
Select Case InKey$
    Case Chr$(13): Cls: _Delay .5: Run
    Case Chr$(27): System
    Case Chr$(9): Cls: GoTo search
End Select
System

assemble:
a$ = a$ + Mid$(a2$, 1, q - 1) + x$
a2$ = Mid$(a2$, q + 1)
Return

Basically I'm just curious about my approach, different approaches, and use. If you can think of another use, different output, or different build approach, I'd enjoy reading the comments and engaging in the conversation.

Pete
Reply
#2
Interesting exercise, Pete! As an example, an HTML file: The search term is found and changed. The changed text can in this case also be copied into an HTML editor, of course.

A problem arises, however, with a longer search term.

That ist OK:

[Image: Wrap-Suchroutine-Notepad.jpg]

[Image: Wrap-Suchroutine-Homesite.jpg]

That did not work:

[Image: Wrap-Problem-mehr-Worte.jpg]
Reply
#3
It is an interesting challenge, the issue occurs even in our Basic IDE searches. @Pete glad to help get you to 100! Long overdue.
b = b + ...
Reply
#4
@bplus Thanks!

Note to anyone using html to test this: The routine is not an html parser, meaning it will not search wrap tags like <br> or <p></P>. It would also have to handle crap like &nbsp; (non-breaking space) and other html coding for quote marks and other punctuation that could be present. I did not want to venture down that rabbit-hole for this utility.

I did think up a way to determine the location in the original text of each search occurrence that needs to be replaced. This is just needed if the routine was to ever be incorporated into a wysiwyg or wp app. It would allow the text found to be highlighted.

I also think I thought up a way to put arrays in place of the string characters that I used to mark the search and replace positions. I'll code it late and see if it pans out.

Oh, @Kernelpanic In image #2 you searched for:

Burg Eisenhardt in Belzig 

when you needed to search for 

'Burg Eisenhardt' in Belzig

Not including the ' marks in the search is why it didn't find it. The routine is not case-sensitive, but that is as AI as it gets. So except for case, the search term needs to match exactly.

Thanks for testing it though. Very much appreciated!

Pete
Reply




Users browsing this thread: 1 Guest(s)