text_replace for one text string



The function text_replace is a one-string
tool which can be used to process a text 
file using higher level functions which
operate on files.


The function text_replace  has the various 
incantations:

  text_replace(snew,sold,string)
          replaces all *distinct* text substrings
          by snew and returns a new string.
        
        text_replace(snew,sold,string, distinct)
         does exactly the same thing.
        
        text_replace(snew,sold,string, all)
           replaces *all* text substrings sold,
           whether or not they are separate words.
        
        text_replace(snew,sold,string, 2) 
          replaces the  *2nd* substring sold
          found in string using the 'all'  mode.
        
         text_replace calls sloc and sword. (see below)
------------------------
Example of use:

(%i1) (display2d:false)$
(%i2) load(replace);
(%o2) "c:/work2/replace.mac"

(%i3) ls : "This is line one isn't it?"$

(%i4) text_replace ("was","is",ls,1);
(%o4) "Thwas is line one isn't it?"

(%i5) text_replace ("was","is",ls,2);
(%o5) "This was line one isn't it?"

(%i6) text_replace ("was","is",ls,3);
(%o6) "This is line one wasn't it?"

(%i7) text_replace ("was","is",ls,4);
" string does not contain that many substrings"

(%o7) "This is line one isn't it?"

(%i8) text_replace ("was","is",ls);
(%o8) "This was line one isn't it?"

(%i9) text_replace ("was","is",ls,distinct);
(%o9) "This was line one isn't it?"

(%i10) text_replace ("was","is",ls,all);
(%o10) "Thwas was line one wasn't it?"

----------------------------------------
text_replace code:
-------------------------------------
text_replace ([%w]) :=    
     
       block ([sn,so,as,%mode:distinct,lso,lsn,nloc,n1,as1],
         sn : part (%w,1),
         so : part (%w,2),
         as : part (%w,3),
         if length (%w) > 3 then
            %mode : part (%w,4),
            
         if listp (%mode) then 
           (disp (" fourth arg cannot be a list "),
             return (as)),
            
         if integerp (%mode) then 
           (nloc : sloc (as,so,%mode),            
           
           if not nloc then (
               disp (" string does not contain that many substrings"),
               return (as)),             
           
           return (ssubstfirst (sn,so,as,nloc))),
            
         if %mode = all then
           return (ssubst (sn,so,as)),
           
         /* case only subst for distinct separate 
             words (the default case)  */
             
         lso : slength(so),
         lsn : slength(sn),      
         
         n1 : sword (as,so,1),
         if not n1 then return (as),
         as1 : ssubstfirst(sn,so,as,sequal,n1,n1+lso),
         /* is that the end of the string as1? */
         if n1 + lsn -1 = slength (as1) then return (as1),
         
         
         do (
           n1 : sword (as1,so,n1+lsn),
           if not n1 then return(),
           as1 : ssubstfirst(sn,so,as1,sequal,n1,n1+lso),
           if n1 + lsn -1 = slength(as1) then return()),
           
         as1)$
  ----------------------------------------------------

text_replace calls sloc.

 sloc (string, substring, n)  finds the
string position of the n'th appearance of
the substring, ignoring distinctness.
Returns false if  no n'th appearance.

 (%i11) sloc (ls,"is",1);
(%o11) 3
(%i12) sloc (ls,"is",2);
(%o12) 6
(%i13) sloc (ls,"is",3);
(%o13) 18
(%i14) sloc (ls,"is",4);
(%o14) false

code:
------------------------------------
    sloc(bs,bo,bn) := 
     block ([lbs,lbo,nbs,nsearch:0  ],
     
      lbs : slength (bs),
      lbo : slength (bo),
      
      /* search for first substring location */
      nbs : ssearch (bo,bs,sequal,1),
      nsearch : nsearch + 1,
      if not nbs then return (false),
      if nsearch = bn then return (nbs),
      if nbs + lbo -1 = lbs then return(false),
      
      do 
       (nsearch : nsearch + 1,
        nbs : ssearch (bo,bs,sequal,nbs+1),
        if not nbs then return(),
        if nsearch = bn then return(),
        if nbs + lbo -1 = lbs then return()),
        
      nbs)$
    -----------------------------------------

  text_replace also calls sword, whose code is:

------------------------------------------------
/************************ sword ***********************/

  /* sword(string,substring,nstart) 
       starts search at char pos nstart
       and
      returns false if text substring is not
      found or if text substring is found but
      is not a separate word.
      
      Otherwise returns the postion
      of the start of the first text substring
      found.
      
      sword calls sword1.
      
        */
  
  sword (%ls,%ss,%nstart) := 
    block ([%ln,%sl,%ns,%nnew,%sep ],
    
      %ln : slength (%ls),
      %sl : slength (%ss),                  
      %ns : ssearch (%ss,%ls,sequal,%nstart),             
      
      /* if substring is not found in
          the string beginning the
          search at %nstart, ssearch returns
          false */
          
      if not %ns then return(false),
      
      /* here we know %ns is some integer 
          and is the position of the first
          substring found so far */
      
      /* check if it is a separate word */
      
      %sep : sword1 (%ls,%ns,%sl),
            
      if %sep then return(%ns),
      
      /* is substring found at end of the line? */
      
      if %ns + %sl -1 = %ln then return (false),
      
      /* search for possible next substring */
      
      %nnew : %ns + 1,
       do
       (%ns : ssearch (%ss,%ls,sequal,%nnew),
        if not %ns then return(),
        if sword1(%ls,%ns,%sl) then return(),
        if %ns + %sl -1 = %ln then (
           %ns : false,
           return())
         else %nnew : %ns + 1),
        
      %ns)$
      --------------------------

  finally, sword calls sword1, whose code is:

  ----------------------

/***************  sword1  ***********************/

   /* sword1(string,nbegin,nlength) returns either
      true or false depending on whether the text substring
      (beginning at nbegin and having length nlength)
      is a separate word. */
      
  sword1 (%ms,%p,%q) := 
    block ([%sleft:false,%sright:false ],
       /* check left hand side of substring */
       
      if (%p = 1) or (not alphanumericp (charat (%ms,%p - 1)))
        then %sleft : true,
        
         /* now check right hand side */
         
      if (%p + %q - 1 = slength (%ms)) or
              (not alphanumericp (charat (%ms,%p + %q)))
              then %sright : true,
              
       if %sleft and %sright then true else false )$

------------------------------------------
Ted Woollett