stephan
stephan

Reputation: 45

How to verify that the last character in a string is a number

I need to check if the last character in a string is a digit, and if so, increment it.

I have a directory structure of /u01/app/oracle/... and that's where it goes off the rails. Sometimes it ends with the version number, sometimes it ends with dbhome_1 (or 2, or 3), and sometimes, I have to assume, it will take some other form. If it ends with dbhome_X, I need to parse that and bump that final digit, if it is a digit.

I use split to split the directory structure on '/', and use include? to check if the final element is something like "dbhome". As long as my directory structure ends with dbhome_X it seems to work. As I was testing, though, I tried a path that ended with dbhome, and found that my check for the last character being a digit didn't work.

db_home = '/u01/app/oracle/product/11.2.0/dbhome'

if db_home.split('/')[-1].include?('dbhome')
  homedir=db_home.split('/')[-1]
  if homedir[-1].to_i.is_a? Numeric
    homedir=homedir[0...-1]+(homedir[-1].to_i+1).to_s
    new_path="/"+db_home.split('/')[1...-1].join("/")+"/"+homedir.to_s
  end
else
  new_path=db_home+"/dbhome_1"
end

puts new_path

I did not expect the output to be /u01/app/oracle/11.2.0/product/dbhom1 - it seems to have fallen into the if block that added 1 to the final character.

If I set the initial path to /u01/app/.../dbhome_1, I get the expected /u01/app/.../dbhome_2 as the output.

Upvotes: 0

Views: 324

Answers (5)

the Tin Man
the Tin Man

Reputation: 160551

This is a starting point if you're running Ruby v2.6+:

fname = 'filename1'

fname[/\d+$/].then { |digits|
  fname[/\d+$/] = digits.to_i.next.to_s if digits
}

fname # => "filename2"

And it's safe if the filename doesn't end with a digit:

fname = 'filename'

fname[/\d+$/].then { |digits|
  fname[/\d+$/] = digits.to_i.next.to_s if digits
}

fname # => "filename"

I'm not sure if I like doing it that way better than the more traditional way which works with much older Rubies:

digits = fname[/\d+$/]
fname[/\d+$/] = digits.to_i.next.to_s if digits

except for the fact that digits gets stuck into the variable space after only being used once. There's probably worse things that happen in my code though.

This is taking advantage of String's [] and []= methods.

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110675

'/u01/app/11.2.0/dbhome'.sub(/\d\z/) { |s| s.succ }
  #=> "/u01/app/11.2.0/dbhome"

'/u01/app/11.2.0/dbhome9'.sub(/\d\z/) { |s| s.succ }
  #=> "/u01/app/11.2.0/dbhome10" 

Upvotes: 0

iGian
iGian

Reputation: 11183

I need to check if the last character in a string is a digit, and if so, increment it.

This is one option:

s = 'string9'

s[-1].then { |last| last.to_i.to_s == last ? [s[0..-2], last.to_i+1].join : s }

#=> "string10"

Upvotes: 0

Zachary Weed
Zachary Weed

Reputation: 21

You could use a regular expression to make matching a tad bit easier

if !!(db_home[/.*dbhome.*\z]) ..

Upvotes: 1

G4143
G4143

Reputation: 2829

You could use regex's

/[0-9]$/.match("How3").nil?

Upvotes: 1

Related Questions