Extract digits from a text object

Get help using and writing Nisus Writer Pro macros.
Post Reply
allenwatson
Posts: 21
Joined: 2005-10-05 15:05:51
Location: Portland, OR
Contact:

Extract digits from a text object

Post by allenwatson »

Very basic question but this macro language is confusing to me. :?

I have a text object, $ref, which contains a string, "Lesson 29". I want to extract the digits (which can be n to nnn) into another text object, call it $refNum. How do I do that? Is there a simple way to use some kind of "find" command with "\d+"? I looked at "substring", having been used to "substr" in another program language, but I can't understand the documentation. A find with regex would be better since it would trap the digits regardless of length.

allenwatson
Posts: 21
Joined: 2005-10-05 15:05:51
Location: Portland, OR
Contact:

Re: Extract digits from a text object

Post by allenwatson »

Alternatively, I could use a find & replace operation that would replace "Lesson " with "W-", resulting in "W-29".

User avatar
phspaelti
Posts: 1202
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Extract digits from a text object

Post by phspaelti »

Hello Allen,
This being Nisus you will be doing this with Find/Replace no matter what.

To start with the solution, this will get you what you want:

Code: Select all

$ref.find "(?<refnum>d+)", "E¢"
Basically, you can do Find/Replace on text objects in more or less the same way that you would do them in the app itself. So if we compare the following two things:

Code: Select all

Find "\d+", "E"
$mytext.find "\d+", "E"
they will both find the first string of digits in the relevant text object. The menu command "Find" will actually create a selection in the GUI, while the latter will return a 'virtual' selection, in the form of a TextSelection object. If you catch the result(s) as follows:

Code: Select all

$result = Find "\d+", "E"
$result = $mytext.find "\d+", "E"
The former will still create the selection in the GUI, and $result will return the number of hits. The latter will return a TextSelection object—or in the case of .findAll an array of TextSelection objects.

So one way to extract a number from a text object would be:

Code: Select all

$mytextselection = $mytext.find "\d+", "E"
$refnum = $mytextselection.substring
To understand why you need to do this this way, you will need to check on how TextSelections work (which I wrote about in other threads).
This method can hit its limit when the pattern you are trying to find is more complicated. But ".find" has another method that turns the found bits into variables. You could do the same like this:

Code: Select all

$mytextselection = $mytext.find "\d+", "E¢"
$refnum = $0
In this case using the "¢" option—only possible with single hit .find, not with .findAll—returns the found bits as number variables: $0 for the whole thing, $1 for the first match, $2 for the second, etc.
The "¢" option also allows you to name the variables yourself. For this you need to use (?<variable_name> … ) match parentheses. This is only possible using PowerFind Pro. That leads to the above mentioned solution.
philip

User avatar
phspaelti
Posts: 1202
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Extract digits from a text object

Post by phspaelti »

PS: I should also mention that you can use this with more complicated Find patterns. So if you wanted to ensure that the digits are after the string "Lesson " you could do it like this:

Code: Select all

$ref.find "Lesson (?<refnum>\d+)", "E¢"
If this doesn't match anything in $ref, then $refnum will be undefined.
philip

User avatar
martin
Official Nisus Person
Posts: 4973
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: Extract digits from a text object

Post by martin »

Thanks to Philip for covering this topic and giving some nice examples. I'll only reply to add a few technical terms and links.

Code: Select all

$text = 'Lesson 11'
$text.find '\d+', 'E¢'
Prompt $0
This works because of the ¢ option specific to the Nisus macro language. It converts the standard regular-expression (regex) full match \0 into a $0 macro variable. For more details on the ¢ and $ options please see the Find & Replace section of the macro reference.

Code: Select all

$text = 'Lesson 21'
$text.find 'Lesson (\d+)', 'E¢'
Prompt $1
This works because of the explicit capture in the regular expression. The \1 back-reference is converted into a $1 macro variable.

Code: Select all

$text = 'Lesson 31'
$text.find 'Lesson (?<lessonNumber>\d+)', 'E¢'
Prompt $lessonNumber
This utilizes the named capture feature of regular expressions. The Nisus macro language picks up your capture's name and creates appropriate local variables.

allenwatson
Posts: 21
Joined: 2005-10-05 15:05:51
Location: Portland, OR
Contact:

Re: Extract digits from a text object

Post by allenwatson »

Thank you lots for this extensive and detailed explanation!

At first I tried all the variations and they all failed. After a LONG time and many tries, I finally realized that, in copying your code from the forum, the quotation marks came through as double smart quotes. I used your first example, changing the smart quotes to straight quotes, and it worked perfectly. Thank you! :D

Post Reply