Jump to content

Recommended Posts

Posted

Hello .

 

Suppose that I have a text (abcd-Mech,01) and I want to replace chars within the text ( -Mech, ) to be -Me-

 

what is the right way to make ?

 

Thanks

 

Michaels

  • Replies 25
  • Created
  • Last Reply

Top Posters In This Topic

  • Michaels

    10

  • pBe

    9

  • irneb

    4

  • lpseifert

    1

Top Posters In This Topic

Posted
(vl-string-subst "-Me-" "-Mech," "abcd-Mech,01")

Posted

Thanks a lot .

 

I would like to change a specific char which is after (HYPHEN) to be (-Me- or -Much- or whatever) for example .

(defun c:test (/ ss ss1 str place)
 (if (setq ss (ssget '((0 . "TEXT"))))
  (progn
    (setq ss1 (ssname ss 0))
      (setq str (cdr (assoc 1 (setq ent (entget ss1)))))
       (setq place (vl-string-search "-" str))
         ( .................

 

Appreciated

Posted (edited)

as lpseifert noted

 

Try This :

 

 
(defun c:test (/ doc)
(vl-load-com)
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(if
 (ssget '((0 . "*TEXT")))
 (vlax-for txt (vla-get-activeselectionset doc)
     (vla-put-textstring txt
      (vl-string-subst "-Mech" "-" (vla-get-textstring txt)
   (vl-string-search "-" (vla-get-textstring txt))) )
)(princ "\nNo Text selected:")
 )
(princ)     
)

 

Note: if there are two (2) "-" on your text it will only replace the first one found

depending on your needs, we can revise it to loop back.. :)

 

hope this helps

 

Also we can add user input for string to find and string to substitute if needed

Edited by pBe
Posted

That's great pBe.

 

But I want to change the complete chars that are existed between the two commas or points .

 

Thanks a lot

Posted
ohh... give me an example

Before:

After:

 

Thank you for your interests. :)

Example .

 

Before 12,abcdef01,34

After 12,new,34

 

I mean all chars that are between the two commas (abcdef01) to be (new)

 

Appreciated

Posted

before anything else, will it always be a comma (,) search? or sometimes a hyphen (-)?

and are you sure there always be (2) two commas on one string value?

So if we encounter string value with just (1) one comma/hypen the code will ignore it?

Posted

It is always between two commas and no matter how many chars are there

Posted

With a very specific set of rules:

 


[b][color=BLACK]([/color][/b]defun rstr-cma [b][color=FUCHSIA]([/color][/b]s ns / c cl[b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]setq c 1[b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]repeat [b][color=NAVY]([/color][/b]strlen s[b][color=NAVY])[/color][/b]
         [b][color=NAVY]([/color][/b]if [b][color=MAROON]([/color][/b]= [b][color=GREEN]([/color][/b]substr s c 1[b][color=GREEN])[/color][/b] [color=#2f4f4f]","[/color][b][color=MAROON])[/color][/b]
             [b][color=MAROON]([/color][/b]setq cl [b][color=GREEN]([/color][/b]cons c cl[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
         [b][color=NAVY]([/color][/b]setq c [b][color=MAROON]([/color][/b]1+ c[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b]
 [b][color=FUCHSIA]([/color][/b]strcat [b][color=NAVY]([/color][/b]substr s 1 [b][color=MAROON]([/color][/b]cadr cl[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
          ns
          [b][color=NAVY]([/color][/b]substr s [b][color=MAROON]([/color][/b]car cl[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b]

[b][color=BLACK]([/color][/b]setq str [color=#2f4f4f]"12,abcfe,34"[/color][b][color=BLACK])[/color][/b]

[b][color=BLACK]([/color][/b]princ [color=#2f4f4f]"\n"[/color][b][color=BLACK])[/color][/b]
[b][color=BLACK]([/color][/b]princ [b][color=FUCHSIA]([/color][/b]rstr-cma str [color=#2f4f4f]"new"[/color][b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b]

 

 

-David

Posted (edited)

Try this:

 

 
(defun test (a b / doc pstn pstn2 otr_hlf) 
(vl-load-com)
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(if
 (ssget '((0 . "*TEXT")))
 (vlax-for txt (vla-get-activeselectionset doc)
(if (and
        (setq pstn (vl-string-search a (vla-get-textstring txt)))
    (setq pstn2 (vl-string-search a (setq otr_hlf (substr (vla-get-textstring txt) (+ pstn 2)))))
    )
  (vla-put-textstring txt
   (strcat (substr (vla-get-textstring txt) 1 (+ pstn 1))  b   (substr otr_hlf  (+ pstn2 1))))
  
    )
       
       
)(princ "\nNo Text selected:")
 )
(princ)     
)

 

 

Usage : (test "," "newtext")

Usage: (test "-" "banana cake")

 

where a is string to search

b is new text

 

works on any char search (i think )

Edited by pBe
Posted

What should I support for (a and b) as in your routine

(defun test (a b / doc)

 

Thanks

 

EDIT: sorry I found it at the end of your last post

Posted

Some food for thought - it could also be achieved using RegularExpressions:

 

(defun test ( string new / RegExp ) (vl-load-com)
 ;; Example by Lee Mac 2011 - www.lee-mac.com

 (setq RegExp (vlax-create-object "VBScript.RegExp"))

 (mapcar
   (function
     (lambda ( prop ) (vlax-put-property RegExp (car prop) (cdr prop)))
   )
   (list
     (cons 'global     actrue)
     (cons 'ignorecase actrue)
     (cons 'multiline  actrue)
     (cons 'pattern    "-.*,")
   )
 )

 (setq string (vlax-invoke RegExp 'replace string new))
 (vlax-release-object RegExp)

 string
)

 

_$ (test "abcd-Mech,01" "-Me-")
"abcd-Me-01"

Posted

Thanks Lee.

 

I can not deal with these kind of codes , so could you please bring one in vanilla ?

 

I would like to understand coding and not only using someone's routine .

 

Appreciated

Posted

Just a query: why not use the FIND command? Or do you have to do this through lisp?

 

You state that you want to replace everything between the 2 commas. Do you know what is existing between the 2, or could it be anything? I.e.

Before:

 

  1. 12,abcdef01,34
  2. 15,zyxwv02,43

After:

 

  1. 12,new,34
  2. 15,new,43

If this is the case, it's a bit more complex - but can be done (as David and pBe's shown). Although I'd start using regular expressions in this case - a bit more advanced than the usual wildcard match as per Find / wcmatch. If you want to go the regular expression way, you could use my code here (or Lee's also got similar in his Batch Replace routine).

 

Whether you use the find command, wildcard or regular expressions you'll probably run into some cases where the characters you're searching for could contain "special" characters. E.g. the comma is used to separate different alternatives in the find and wcmatch. So you then need to "escape" such functionality. In find and wcmatch you do this by prefixing a reverse quote (`) to the special character. In RegEx you'd use the backslash (\) in similar situations.

 

In RegEx you could use my RX:Replace function thus:

(RX:Replace "12,abcdef01,34" ",[^,]+," ",new,") ;==> "12,new,34"
(RX:Replace "15,zyxwv02,43" ",[^,]+," ",new,") ;==> "15,new,43"
(RX:Replace "15,zyxwv02,test,test,43" ",[^,]+," ",new,") ;==> "15,new,test,new,43"
(RX:Replace "15,zyxwv02,test,test,43" ",[^,]+^$" ",new") ;==> "15,zyxwv02,test,test,43"
(RX:Replace "15,zyxwv02,test,test,43" ",.+," ",new,") ;==> "15,new,43"

The last one shows what's known in RegEx as the "greediness" of the "." special character. For a list of special characters see the end of my lisp, or for a more complete description see here.

 

Also a possible problem with pBe's code. The selection filter would also catch RTEXT ... which in turn could cause errors. I'd suggest using "TEXT,MTEXT" instead of "*TEXT".

 

And you could use wildcard matches to capture only text with 2 commas:

'((0 . "TEXT,MTEXT") (1 . "*`,*`,*"))

But it might become less efficient since pBe's code can work for more than just commas - you'll have to strcat and you don't want the reverse quotes when not needed.

 

Edit sorry, yes I just saw you added RegEx's as well Lee. ^%$^^&$&& slow connections %$&$%&%&

Posted
Try this:

 

 
(defun test (a b / doc pstn pstn2 otr_hlf) 
(vl-load-com)
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(if
 (ssget '((0 . "*TEXT")))
 (vlax-for txt (vla-get-activeselectionset doc)
(if (and
        (setq pstn (vl-string-search a (vla-get-textstring txt)))
    (setq pstn2 (vl-string-search a (setq otr_hlf (substr (vla-get-textstring txt) (+ pstn 2)))))
    )
  (vla-put-textstring txt
   (strcat (substr (vla-get-textstring txt) 1 (+ pstn 1))  b   (substr otr_hlf  (+ pstn2 1))))
  
    )
       
       
)(princ "\nNo Text selected:")
 )
(princ)     
)

 

 

Usage : (test "," "newtext")

Usage: (test "-" "banana cake")

 

where a is string to search

b is new text

 

works on any char search (i think )

 

 

Thanks a lot pBe.

 

I do appreciate your hard work and your time on that routine.

Posted

Thanks irneb ,

 

But according to what I thought it could be done in Lisp , first we use (vl-string-search ",") and then locate the place of

that comma and then replace from that point all chars that are included between the two commas to another completely

different chars as needed .

 

The hard part for me was when getting the location of a char what should I do to replace these chars only .

 

Regards

Posted
With a very specific set of rules:

 

[color=navy][color=#000000].....[/color][b]([/b][/color]if [b][color=maroon]([/color][/b]= [b][color=green]([/color][/b]substr s c 1[b][color=green])[/color][/b] [color=#2f4f4f]","[/color][b][color=maroon])[/color][/b]
[b][color=maroon]([/color][/b]setq cl [b][color=green]([/color][/b]cons c cl[b][color=green])[/color][/b][b][color=maroon])[/color][/b][b][color=navy])[/color][/b]
[b][color=navy]([/color][/b]setq c [b][color=maroon]([/color][/b]1+ c[b][color=maroon])[/color][/b][b][color=navy])[/color][/b][b][color=fuchsia])[/color][/b]
[b][color=fuchsia]([/color][/b]strcat [b][color=navy]([/color][/b]substr s 1 [b][color=maroon]([/color][/b]cadr cl[b][color=maroon])[/color][/b][b][color=navy])[/color][/b]
ns
[b][color=navy]([/color][/b]substr s [b][color=maroon]([/color][/b]car cl[b][color=maroon])[/color][/b][b][color=navy])[/color][/b][b][color=fuchsia])[/color][/b][b][color=black])[/color][/b]
.... 

 

 

-David

 

 

Clever David :)

Posted
Some food for thought - it could also be achieved using RegularExpressions:

 

_$ (test "abcd-Mech,01" "-Me-")

"abcd-Me-01"[/code]

 

:shock: Wow, thats new

Cool Lee

Posted
Thanks irneb ,

 

But according to what I thought it could be done in Lisp , first we use (vl-string-search ",") and then locate the place of

that comma and then replace from that point all chars that are included between the two commas to another completely

different chars as needed .

 

The hard part for me was when getting the location of a char what should I do to replace these chars only .

 

Regards

I advise the RegEx for 2 reasons:

 

  1. It's much simpler to code
  2. It's a lot more efficient

AutoLisp is rather pedestrian when you're working with strings. The visual lisp extensions help a bit, but not as much as you get in other languages. The regular expressions are basically the most powerful string handling you can get these days.

 

But to explain the thing through pBe & Davids code methods:

 

Using pure AutoLisp you'd have to step through each character in the string then test it using substr. Note where it is. Continue to find the next, note that as well. Then extract the portion prior to & including the found character, as well as the portion from the 2nd onwards (this you do using substr with the previously found 2 positions). Then use strcat to combine them with the new portion in between. Pure ALisp doesn't have any way of "replacing" text, only methods for extracting portions (substr) and combining (strcat). That's why I said pedestrian.

 

Using VLisp you can use the vl-string-subst function which uses a much more efficient way of "replacing" one text portion with another. You still need to find the position of the 1st and 2nd search characters - in which case you can use the vl-string-search function so you don't need to step through each character in turn. But then just remember that using the vl stuff you're working with 0-based-index (i.e. the 1st character in the string has an index of 0), unlike with substr which is 1-based. This sometimes screws one's head around when mix-n-matching the 2.

 

For a direct replacement, the regex stuff is a single call. It replaces the relevant portions on its own - using extremely efficient string handling internally. You don't need to even worry about where it's found - that's handled by regex itself.

 

When you have something a bit more complex, the regex is not as perfect (at least not Microsoft's version of it). As an example see the sample functions in my routine to generate sentence case. The problem is you need to use the found portion (which would be the 1st character of each sentence) and then strcase it to convert to upper case - the rest to be converted to lower. And then you need to strcat the portions together again. Some of the other languages' regex libraries allow direct calls to functions when replacing - thus not needing the concatenation any-more. Unfortunately we're stuck with M$'s version though. :roll:

 

BTW, due to AutoLisp's inefficiency with strcat, I've modified my code a bit to use a list of portions then do a single strcat at the end. See from line 181 onwards to 190 in this revision. I suppose I could have used vl-string-subst instead, but if it would make a difference in efficiency I don't know (multiple calls to vl-string-subst as compared to one call of strcat). And since lisp is highly optimized for working with lists, the new way might just be fast already.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...