# Help in my own gsub design

**URL:** <https://www.ruby-forum.com/t/help-in-my-own-gsub-design/116109>\
**Category:** Ruby\
**Created:** [October 2, 2007, 1:41pm UTC](https://www.ruby-forum.com/t/help-in-my-own-gsub-design/116109 "2007-10-02T13:41:19Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 2, 2007, 1:41pm UTC](https://www.ruby-forum.com/t/help-in-my-own-gsub-design/116109/1 "2007-10-02T13:41:19Z")

</div>

I don’t use it very often, rather copying from example, but it’s so  
useful that I should learn how to write it  
I’d appreciate any guru tip on how to proceed once the problem is on  
the paper :

example :

INPUT STRINGS

1- input can contains spaces (should be eliminated)

2- good patterns :

2a- an Integer like 99 (no limit)  
a \> \>= \< \<= \<\> != followed by an Integer like \>99

> =99 \<99 \<=99 \<\>99 !=99

2b- a String like: abcd abc99 99abc a99bc

2c- a % sign followed by a String  
like %abcd %abc99 %99abc %a99bc %abcd

2d- a String followed by a % sign  
like abcd% abc99% 99abc% a99bc%

2e- a String leading containing or ending with, one or many \* sign(s)  
like a_bcd a\*\*bc99 99_a_bc a99bc a99bca99bca9\*\*9bc_

3-any other pattern will be considered as wrong

OUTPUTS

2a -\> an array [characters, Integer] like [“\<\>”, 99]  
2b, 2c, 2d,2e -\> an array [nil, String] like [nil, abcd] or [nil,  
%abcd] or [nil, a99bc%] or [nil, _a9\*\*9b_c]

I am interesting in understanding the design process… : how should I  
start when designing such gsub routine ?  
should I state it differently on paper first ? well, any tip that can  
help me to build the next ones…

thanks for your support

joss

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 2, 2007, 2:50pm UTC](https://www.ruby-forum.com/t/help-in-my-own-gsub-design/116109/2 "2007-10-02T14:50:38Z")

</div>

On Oct 2, 6:35 am, Josselin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> like %abcd %abc99 %99abc %a99bc %abcd
> 
> ```
> 
> joss

def foo s  
case s  
when /^(\>|\>=|\<|\<=|\<\>|!=)?(\d+)$/  
[$1 || “”, $2.to\_i]  
when /^(%)?[a-z\d]+(%)?$/  
return nil if 1 != $~.captures.compact.size  
[nil, $&]  
when /^(?=.\*\*)[\*a-z\d]+$/  
[nil, $&]  
end  
end

p foo( “88” )  
p foo( “\<\>88” )  
p foo( “%33” )  
p foo( “33%” )  
p foo( “a\*9” )  
p foo( ‘bat’ )

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 2, 2007, 3:25pm UTC](https://www.ruby-forum.com/t/help-in-my-own-gsub-design/116109/3 "2007-10-02T15:25:53Z")

</div>

On 2007-10-02 14:46:48 +0200, William J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) said:

> > 1- input can contains spaces (should be eliminated)  
> > 2c- a % sign followed by a String  
> > OUTPUTS  
> > thanks for your support  
> > when /^(?=.\*\*)[\*a-z\d]+$/  
> > [nil, $&]  
> > end  
> > end
> 
> p foo( “88” )  
> p foo( “\<\>88” )  
> p foo( “%33” )  
> p foo( “33%” )  
> p foo( “a\*9” )  
> p foo( ‘bat’ )

thanks a lot , William, I can see how you built it… I just have 2  
points to clarify if you don’t mind

1- return nil if 1 != $~.captures.compact.size  
I don’t catch up

2- (?=.\*\*)

otherwise I commented it … is my understanding correct ?

def foo s  
case s  
when /^(\>|\>=|\<|\<=|\<\>|!=)?(\d+)$/

# start with \> OR \>= OR \< OR \<= OR \<\> OR != (0 or 1 time) then

digit(0-9) n times  
[$1 || “”, $2.to\_i]

# first element or nil , second element to integer

```
when /^(%)?[a-z\d]+(%)?$/

```

# start with % ( 0 or 1 time) then characters a-zA-Z 1 or n times then

end with % ( 0 or 1 time)  
return nil if 1 != $~.captures.compact.size

# return nil if …

```
  [nil, $&]

```

# first element nil, second element = parameter

```
when /^(?=.*\*)[*a-z\d]+$/

```

# start with \*( 0 or n times)… then characters \*a-zA-Z 1 or n

tiems  
[nil, $&]

# first element nil, second element = parameter

end  
end

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 2, 2007, 5:35pm UTC](https://www.ruby-forum.com/t/help-in-my-own-gsub-design/116109/4 "2007-10-02T17:35:39Z")

</div>

On Oct 2, 10:12 am, William J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> This is a good point. Instead of $& (what was matched by the reg.ex.)  
> I should  
> have used the parameter of the function, s.

But s may have unwanted spaces. Stick with $&.

---

<div class="post-metadata">

**Author:** ![Josselin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9de0a6/32.png) [@Josselin](https://www.ruby-forum.com/u/Josselin)\
**Post date:** [October 2, 2007, 5:16pm UTC](https://www.ruby-forum.com/t/help-in-my-own-gsub-design/116109/5 "2007-10-02T17:16:14Z")

</div>

On Oct 2, 8:24 am, Josselin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > INPUT STRINGS  
> > > 2b- a String like: abcd abc99 99abc a99bc  
> > > 3-any other pattern will be considered as wrong  
> > > help me to build the next ones…  
> > > return nil if 1 != $~.captures.compact.size  
> > > p foo( “a\*9” )  
> > > p foo( ‘bat’ )
> 
> thanks a lot , William, I can see how you built it… I just have 2  
> points to clarify if you don’t mind
> 
> 1- return nil if 1 != $~.captures.compact.size  
> I don’t catch up

I wrote the function so that it will return nil if the string  
doesn’t match your patterns. The line above is equivalent to

if 1 != $~.captures.compact.size  
return nil  
end

The number of succesful captures (captured by /^(%)?[a-z\d]+(%)?$/ )  
must  
be exactly 1; i.e., the string must begin or end with %, but not both.

> 2- (?=.\*\*)

(?=…) is a zero-width look-ahead; it looks ahead but it doesn’t  
move ahead in the string. I put this here to make sure that the  
string contains at least one \*.

> otherwise I commented it … is my understanding correct ?
> 
> def foo s  
> case s

I forgot about spaces. If they can only be at the start or end of the  
string, use  
case s.strip

> ```
> when /^(>|>=|<|<=|<>|!=)?(\d+)$/
> # start with > OR >= OR < OR <= OR <> OR != (0 or 1 time) then
> 
> ```
> 
> digit(0-9) n times

1 or more times.

> ```
> [$1 || "", $2.to_i]
> # first element or nil , second element to integer
> 
> ```

If 1st capture is nil, use “”; else use 1st capture.

> ```
> when /^(%)?[a-z\d]+(%)?$/
> # start with % ( 0 or 1 time) then characters a-zA-Z 1 or n times then
> 
> ```
> 
> end with % ( 0 or 1 time)  
> return nil if 1 != $~.captures.compact.size  
> # return nil if …  
> [nil, $&]  
> # first element nil, second element = parameter

This is a good point. Instead of $& (what was matched by the reg.ex.)  
I should  
have used the parameter of the function, s.
