Hello Ruby friends!
I'm learning ruby and i already have some problems.
I have a file with Login and Ip address but not on the same line.
Exemple :
Login1
Address1
Login2
Address2
....
I searh a way to extract the IP address when i search the login
search.rb Login2
> address2
I know how to search a pattern :
Login= File.open("users" ).each_line.grep( /Login2/ )
puts Login
First question : how can i see the line after ? the line with the Ip
address of that login
Second question : I don't search always the same pattern so i need to
pass an argument to my script. I tried this
Login= File.open("users" ).each_line.grep( /ARGV[0]/ )
puts Login
but it doesn't show anything
Third question : After having the ip address, i need to make an ssh
connection to this address. How can i get a variable to be usable in
system("ssh $variable") ?
Thanks for your help and sorry for my english, i hope it's
understandable.
Ydil
on 2010-02-04 11:58
on 2010-02-04 12:35
On 02/04/2010 11:58 AM, John Ydil wrote: > Address2 > puts Login > > First question : how can i see the line after ? the line with the Ip > address of that login You could use #each_slice for this (see below). > Second question : I don't search always the same pattern so i need to > pass an argument to my script. I tried this > Login= File.open("users" ).each_line.grep( /ARGV[0]/ ) > puts Login > but it doesn't show anything You need string interpolation in the regular expression. In your case the regexp will match if there is "ARGV0" somewhere in the string - certainly not what you wanted. :-) If your file only contains login and password alternating you could do def lookup(file, user) File.foreach(file).each_slice 2 do |name, pwd| name.strip! pwd.strip! return pwd if user === name end # not found nil end So, how does this work? File.foreach(file) without a block creates an Enumerator, i.e. something that behaves like an Enumerable. With #each_slice(2) iteration will yield two subsequent values at a time: irb(main):012:0> (1..10).each_slice 2 do |a| p a end [1, 2] [3, 4] [5, 6] [7, 8] [9, 10] => nil irb(main):013:0> Now we have File.foreach(file) instead of 1..10 so what happens here is that lines are read from the file and returned in pairs to the block. The block checks whether there is a match (after removing trailing newlines) and returns from the method if it finds something. You can use this with regular expressions *and* Strings because of ===: pwd = lookup "users", ARGV[0] pwd = lookup "users", /#{ARGV[0]}/ If you want to do string matching and need to match multiple times during a single script execution you could as well load the file into a Hash user_password = Hash[*(File.foreach(file).map {|s| s.chomp})] This will work only if your file has an even number of lines though. > Third question : After having the ip address, i need to make an ssh > connection to this address. How can i get a variable to be usable in > system("ssh $variable") ? You can use regular string interpolation system "ssh #{your_variable}" AFAIK there is also a SSL / SSH library for Ruby. You should probably look into that as well. > Thanks for your help and sorry for my english, i hope it's > understandable. No problem. Kind regards robert
on 2010-02-05 00:10
Robert Klemme wrote:
> File.foreach(file).each_slice 2 do |name, pwd|
How is it better than 'File.open(file).each_slice' ?
on 2010-02-05 07:31
On Thu, Feb 4, 2010 at 5:35 AM, Robert Klemme <shortcutter@googlemail.com>wrote: > > The book "Practical Ruby Gems" suggests net-ssh ( http://gemcutter.org/gems/net-ssh), and has a six page example of a simple use program that logs onto a remote server with SSH and uses Vim to edit a text file. It also has an example of net-sftp. (though one of those was outdated, I think the net-sftp version had changed)
on 2010-02-05 08:24
On 05.02.2010 00:10, Albert Schlef wrote: > Robert Klemme wrote: >> File.foreach(file).each_slice 2 do |name, pwd| > > How is it better than 'File.open(file).each_slice' ? It closes the file handle properly which your variant doesn't do. Kind regards robert
on 2010-02-05 10:46
John Ydil wrote: > Third question : After having the ip address, i need to make an ssh > connection to this address. How can i get a variable to be usable in > system("ssh $variable") ? That would be either system("ssh",variable) # you split the args or system("ssh #{variable}" # shell splits the args But this is probably not what you want, unless you're just using ssh to execute a single command remotely, and you're using RSA keys so you're not going to be prompted for a passwords. Have a look at Net::SSH and Net::SSH::Telnet (the latter wraps Net::SSH in an API which is a drop-in replacement for Net::Telnet)
on 2010-02-05 10:59
Josh Cheek wrote: > On Thu, Feb 4, 2010 at 5:35 AM, Robert Klemme > <shortcutter@googlemail.com>wrote: > >> >> > The book "Practical Ruby Gems" suggests net-ssh ( > http://gemcutter.org/gems/net-ssh), and has a six page example of a > simple > use program that logs onto a remote server with SSH and uses Vim to edit > a > text file. It also has an example of net-sftp. (though one of those was > outdated, I think the net-sftp version had changed) Thanks for your help but the ssh command was an exemple :p In fact, i need to check routes on a linux router. It's a light linux distribution, i can't install anything. There is ruby 1.8.2 inside that's why i'm learning how to use it. New question ! Thanks to Robert, I have my IP address (Youhou) I need to check the route with this IP address. the linux command is "ip route get {IP address}" so my command is : system("ip route get #{ipaddress}") but the result of this, is just true or false. How can I put the result of my command in a variable ? regards, Ydil
on 2010-02-05 12:50
Robert Klemme wrote: > On 05.02.2010 00:10, Albert Schlef wrote: >> Robert Klemme wrote: >>> File.foreach(file).each_slice 2 do |name, pwd| >> >> How is it better than 'File.open(file).each_slice' ? > > It closes the file handle properly which your variant doesn't do. You mean, that in my version the file isn't closed till the file object gets destroyed by the garbage collector? I see. (I assume the enumerator returned by foreach() mimics foreach()'s behaviour; that is, that it closes the file after the last iteration.)
on 2010-02-05 13:07
On Fri, Feb 5, 2010 at 3:59 AM, John Ydil <john.gendrot@cnsi.fr> wrote: > the linux command is "ip route get {IP address}" > so my command is : system("ip route get #{ipaddress}") but the result of > this, is just true or false. How can I put the result of my command in a > variable ? > > You can use %x( ... ) for this, those parentheses can also be things like brackets or pipes, even @ symbols. So, for example: dir_list = %x(ls -l) puts "The directory's listing is:" puts dir_list
on 2010-02-05 13:08
On 02/05/2010 12:50 PM, Albert Schlef wrote: > Robert Klemme wrote: >> On 05.02.2010 00:10, Albert Schlef wrote: >>> Robert Klemme wrote: >>>> File.foreach(file).each_slice 2 do |name, pwd| >>> How is it better than 'File.open(file).each_slice' ? >> It closes the file handle properly which your variant doesn't do. > > You mean, that in my version the file isn't closed till the file object > gets destroyed by the garbage collector? Exactly. > I see. > > (I assume the enumerator returned by foreach() mimics foreach()'s > behaviour; that is, that it closes the file after the last iteration.) It does not _mimic_ the behavior, it _uses_ it!! irb(main):001:0> class X irb(main):002:1> def self.foreach irb(main):003:2> if block_given? irb(main):004:3> puts "open" irb(main):005:3> yield 123 irb(main):006:3> puts "close" irb(main):007:3> else irb(main):008:3* Enumerator.new(self, :foreach) irb(main):009:3> end irb(main):010:2> end irb(main):011:1> end => nil irb(main):012:0> X.foreach {|x| p x} open 123 close => nil irb(main):013:0> X.foreach.map {|x| x + 10000} open close => [10123] irb(main):014:0> Kind regards robert
on 2010-02-05 14:01
Robert Klemme wrote: > On 02/05/2010 12:50 PM, Albert Schlef wrote: >> Robert Klemme wrote: >>> On 05.02.2010 00:10, Albert Schlef wrote: >>>> Robert Klemme wrote: >>>>> File.foreach(file).each_slice 2 do |name, pwd| >>>> How is it better than 'File.open(file).each_slice' ? >>> It closes the file handle properly which your variant doesn't do. >> >> You mean, that in my version the file isn't closed till the file object >> gets destroyed by the garbage collector? > > Exactly. > >> I see. >> >> (I assume the enumerator returned by foreach() mimics foreach()'s >> behaviour; that is, that it closes the file after the last iteration.) > > It does not _mimic_ the behavior, it _uses_ it!! > > irb(main):002:1> def self.foreach > irb(main):003:2> if block_given? > [...] > irb(main):007:3> else > irb(main):008:3* Enumerator.new(self, :foreach) > irb(main):009:3> end > irb(main):010:2> end Nice. Pheeew, I still have a long road to walk before I acquire the "Ruby way of thinking". Robert, thanks. Whenever I read your answers here, even to the most trivial questions, I'm treated to some eye-opening gems. I'm generally aware of the power of Ruby, but oftentimes it seems to me unleashing it would involve a few lines of code, whereas you do it easily in just one line of it.
on 2010-02-05 19:53
On 02/05/2010 02:01 PM, Albert Schlef wrote: >> Exactly. >> irb(main):007:3> else >> irb(main):008:3* Enumerator.new(self, :foreach) >> irb(main):009:3> end >> irb(main):010:2> end > > Nice. Pheeew, I still have a long road to walk before I acquire the > "Ruby way of thinking". Hmm, maybe it helps that I practice a Japanese martial art. ;-) > Robert, thanks. Whenever I read your answers here, even to the most > trivial questions, I'm treated to some eye-opening gems. You're welcome! I'm glad that I could help. I am always amazed how friendly our community is compared to others and I try to maintain that by sharing what I believe to have understood about the language. > I'm generally aware of the power of Ruby, but oftentimes it seems to me > unleashing it would involve a few lines of code, whereas you do it > easily in just one line of it. Well, it might look easy but of course I don't post all the failed tests and attempts that end in dead end streets in order to not distract from the content I want to convey. :-) Kind regards robert
on 2010-02-08 14:07
Robert Klemme wrote: > On 02/05/2010 02:01 PM, Albert Schlef wrote: >>> Exactly. >>> irb(main):007:3> else >>> irb(main):008:3* Enumerator.new(self, :foreach) >>> irb(main):009:3> end >>> irb(main):010:2> end >> >> Nice. Pheeew, I still have a long road to walk before I acquire the >> "Ruby way of thinking". > > Hmm, maybe it helps that I practice a Japanese martial art. ;-) > Not to completely derail the conversation here (oops?) but, as a parenthesis.. Which one?
on 2010-02-08 15:13
2010/2/8 Aldric Giacomoni <aldric@trevoke.net>: >> >> Hmm, maybe it helps that I practice a Japanese martial art. ;-) >> > Not to completely derail the conversation here (oops?) but, as a > parenthesis.. Which one? http://en.wikipedia.org/wiki/Aikido Kind regards robert
on 2010-02-11 15:53
Hi, me again...
As i said before, I "play" with ruby on a light linux (ruby 1.8.2).
I made my script on my computer (ruby 1.8.7) and move it to my linux.
I works fine on my computer but an error occured when i launch it on my
linux.
Here is my code :
File.foreach("/etc/raddb/users").each_slice 4 do |name, ip, dump, table|
puts name.strip!
puts ip.strip!
puts table.strip!
end
here is the file /etc/raddb/users
login Auth-Type :=Local, User-Password == "bonjour"
Framed-IP-Address = ipaddress,
Fall-Through = No
# table 254
Here is the error :
./test.rb:12:in `foreach': no block given (LocalJumpError)
from ./test.rb:12
I wonder if it's due to the difference between the 2 versions, Do you
have an idea ?
on 2010-02-11 15:56
John Ydil wrote: > > File.foreach("/etc/raddb/users").each_slice 4 do |name, ip, dump, table| > puts name.strip! > puts ip.strip! > puts table.strip! > end > > here is the file /etc/raddb/users > > login Auth-Type :=Local, User-Password == "bonjour" > Framed-IP-Address = ipaddress, > Fall-Through = No > # table 254 > > > Here is the error : > ./test.rb:12:in `foreach': no block given (LocalJumpError) > from ./test.rb:12 > > I wonder if it's due to the difference between the 2 versions, Do you > have an idea ? Well, for this one, a quick look at the documentation will give you the answer: http://ruby-doc.org/core/classes/IO.html#M002243 "foreach" expects a block. So you can't really do "each slice" on "foreach" since you should do "foreach" on ... er ... each line in the file. Probably you'll do the foreach, and a slice on that line within the code block instead.
on 2010-02-11 16:12
2010/2/11 Aldric Giacomoni <aldric@trevoke.net>: >> login Auth-Type :=Local, User-Password == "bonjour" >> have an idea ? > > Well, for this one, a quick look at the documentation will give you the > answer: > http://ruby-doc.org/core/classes/IO.html#M002243 > > "foreach" expects a block. So you can't really do "each slice" on > "foreach" since you should do "foreach" on ... er ... each line in the > file. > Probably you'll do the foreach, and a slice on that line within the code > block instead. He's on 1.8.2. There you have to do require 'enumerator' File.to_enum(:foreach, "/etc/raddb/users").each_slice 4 do |name, ip, dump, table| puts name.strip! puts ip.strip! puts table.strip! end The convenient feature to return an Enumerator from enumerating methods which expect a block but do not receive it was added in 1.9 and backported to 1.8.7. Kind regards robert
on 2010-02-11 16:41
Robert Klemme wrote: > 2010/2/11 Aldric Giacomoni <aldric@trevoke.net>: >>> login Auth-Type :=Local, User-Password == "bonjour" >>> have an idea ? >> >> Well, for this one, a quick look at the documentation will give you the >> answer: >> http://ruby-doc.org/core/classes/IO.html#M002243 >> >> "foreach" expects a block. So you can't really do "each slice" on >> "foreach" since you should do "foreach" on ... er ... each line in the >> file. >> Probably you'll do the foreach, and a slice on that line within the code >> block instead. > > He's on 1.8.2. There you have to do > > require 'enumerator' > > File.to_enum(:foreach, "/etc/raddb/users").each_slice 4 do |name, ip, > dump, table| > puts name.strip! > puts ip.strip! > puts table.strip! > end > > The convenient feature to return an Enumerator from enumerating > methods which expect a block but do not receive it was added in 1.9 > and backported to 1.8.7. > > Kind regards > > robert I was afraid of this, but : ./test.rb:5:in `require': No such file to load -- enumerator (LoadError) from ./test.rb:5 Maybe I haven't the full ruby because it's a small linux...
on 2010-02-11 17:37
2010/2/11 John Ydil <john.gendrot@cnsi.fr>: >>> "foreach" since you should do "foreach" on ... er ... each line in the >> puts name.strip! > from ./test.rb:5 > > > Maybe I haven't the full ruby because it's a small linux... Oooops! Sorry for the wrong advice. Either that or Enumerator did not exist in 1.8.2 (which is ancient btw - I cannot remember having used it). Kind regards robert
on 2010-02-12 09:24
Robert Klemme wrote: > 2010/2/11 John Ydil <john.gendrot@cnsi.fr>: >>>> "foreach" since you should do "foreach" on ... er ... each line in the >>> � � � �puts name.strip! >> � � � �from ./test.rb:5 >> >> >> Maybe I haven't the full ruby because it's a small linux... > > Oooops! Sorry for the wrong advice. Either that or Enumerator did > not exist in 1.8.2 (which is ancient btw - I cannot remember having > used it). > > Kind regards > > robert So there is no way i can do that in 1.8.2 ?
on 2010-02-12 10:01
2010/2/12 John Ydil <john.gendrot@cnsi.fr>: >> not exist in 1.8.2 (which is ancient btw - I cannot remember having >> used it). >> >> Kind regards >> >> robert > > So there is no way i can do that in 1.8.2 ? You can write Enumerator yourself. It isn't too hard Enum = Struct.new :inst, :args do include Enumerable def each(&b) inst.send(*args, &b) self end end class Object def to_enum(*a) Enum.new(self, a) end end :-) Kind regards robert
on 2010-02-12 10:41
Robert Klemme wrote: > 2010/2/12 John Ydil <john.gendrot@cnsi.fr>: >>> not exist in 1.8.2 (which is ancient btw - I cannot remember having >>> used it). >>> >>> Kind regards >>> >>> robert >> >> So there is no way i can do that in 1.8.2 ? > > You can write Enumerator yourself. It isn't too hard > > Enum = Struct.new :inst, :args do > include Enumerable > > def each(&b) > inst.send(*args, &b) > self > end > end > > class Object > def to_enum(*a) > Enum.new(self, a) > end > end > > :-) > > Kind regards > > robert Thanks again Robert but (there is always a BUT).... I copy paste the code you gave me Enum = Struct.new :inst, :args do include Enumerable def each(&b) inst.send(*args, &b) self end end class Object def to_enum(*a) Enum.new(self, a) end end File.to_enum(:foreach, "/etc/raddb/users").each_slice 4 do |name, ip, dump, table| puts name.strip! puts ip.strip! puts table.strip! end ./test.rb:31: undefined method `each_slice' for #<struct Enum inst=File, args=[:foreach, "/etc/raddb/users"]> (NoMethodError) I think we progress....
on 2010-02-12 13:14
2010/2/12 John Ydil <john.gendrot@cnsi.fr>: > Thanks again Robert but (there is always a BUT).... > > I copy paste the code you gave me > > I think we progress.... Slowly.... I believe #each_slice was added later as well. Oh well. Can't you just upgrade your Ruby version? That seems a much better option than trying to retrofit all the new behavior on the old version. Kind regards robert
on 2010-02-12 14:29
> > Slowly.... I believe #each_slice was added later as well. Oh well. > Can't you just upgrade your Ruby version? That seems a much better > option than trying to retrofit all the new behavior on the old > version. > > Kind regards > > robert I'll try to upgrade.
on 2010-02-15 11:21
John Ydil wrote: > >> >> Slowly.... I believe #each_slice was added later as well. Oh well. >> Can't you just upgrade your Ruby version? That seems a much better >> option than trying to retrofit all the new behavior on the old >> version. >> >> Kind regards >> >> robert > > I'll try to upgrade. Unfortunately, the provider doesn't have a newer version of ruby :s
on 2010-02-15 15:19
2010/2/15 John Ydil <john.gendrot@cnsi.fr>: >>> robert >> >> I'll try to upgrade. > > > Unfortunately, the provider doesn't have a newer version of ruby :s module Enumerable def each_slice(num) sl = [] each do |x| sl << x if sl.size == num yield sl sl = [] end end yield sl unless sl.empty? self end end Kind regards robert
on 2010-02-15 16:53
John Ydil wrote: > > You are awesome ! Robert, indeed, is. Donations can be sent to rk_is_our_idol@awesomeness.wow for attempts at cloning his awesomeness.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.