In expect block of expect script like as below:
expect {
"matched_string" {puts "string is matched"}
"I want to get strings else" {puts "string is unmatched"} #(1)
}
At the (1), I want to get all strings which difference with "matched_string". It is same as "else".I can solve with the default or timeout but I don't want to wait.
How can I do it?
Many thanks.
Related
I want to recall the case until user writes a or b. I do not want to use "case"
particularly.
I just want to get input from user but not geting something else. If he writes something else, he should need to write until he writes a or b.
str = gets.chomp.to_s
case str
when "a"
print "nice a"
when "b"
puts "nice b"
else
puts "please do it again"
end
class person
attr_accessor :name , :surname #and other attributes
end
#There will be a method here and it will run when the program is opened.
#The method will create the first object as soon as the program is opened.
#The new object that the user will enter will actually be the 2nd object.
puts "What do you want to do?
add
list
out"
process = gets.chomp.to_s
case process
when "add"
#in here user will add new objects of my class
when "list"
#in here user will show my objects
when "out"
puts "Have a nice day"
else
puts "please do it again"
end
In fact, if you look at it, many actions will be taken as a result of the user entering the correct input. what I want to tell is more detailed in this example. According to the input of the user, there will be actions such as calling methods, adding objects, etc.
I wrote most of the code on my computer. But still I couldn't solve my first problem.
Use Kernel#loop
There are a lot of ways to solve this problem, but let's start with a simple Kernel#loop wrapper around your existing code, as that's probably the easiest path forward for you.
loop do
str = gets.chomp.to_s
case str
when "a"
print "nice a"
when "b"
puts "nice b"
else
puts "please do it again"
# restart your loop when not "a" or "b"
next
end
# exit the loop if else clause wasn't triggered
break
end
Use until Control Expression
The loop construct above is pretty straightforward, but it requires you to think about where you need next and break statements for flow control. My own instinct would be to simply call a block until it's truthy. For example, the core logic could be shortened to:
str = nil; until str =~ /a|b/i do str = gets.chomp end; p str
This is a lot shorter, but it's not particularly user-friendly. To leverage this approach while making the solution more communicative and error-resistant, I'd refactor the original code this way:
# enable single-character input from console
require 'io/console'
# make sure you don't already have a value,
# especially in a REPL like irb
str = nil
until str =~ /a|b/ do
printf "\nLetter (a, b): "
str = STDIN.getch.downcase
end
puts "\nYou entered: #{str}"
While not much shorter than your original code, it handles more edge cases and avoids branching. It also seems less cluttered to me, but that's more a question of style. This approach and its semantic intent also seem more readable to me, but your mileage may legitimately vary.
See Also
IO::Console
Control Expressions
"I just want to do something until something else happens" is when you use some sort of while loop.
You can do this:
while true
str = gets.chomp
break unless str == 'a' || str == 'b'
puts "please do it again"
end
You can also use loop do:
loop do
str = gets.chomp
break unless ['a', 'b'].include?(str)
puts "please do it again"
end
puts "Nice #{str}."
Rubyists tend to prefer loop do over while true. They do pretty much the same thing.
One more thing. There's a simpler way to write out arrays of strings:
loop do
str = gets.chomp
break unless %w(a b).include?(str)
puts "please do it again"
end
puts "Nice #{str}."
It doesn't look a whole lot simpler, but if you have, say, 10 strings, it's definitely quicker to type in when you don't have to use all those quotation marks.
As your intuition was telling you, you don't need to use the case statement at all. Like trying to kill a flea with a sledgehammer. The most concise way to do your check is to check whether the input character is included in an array of the desired characters.
I am new to Ruby.
I need to make this script work:
puts "Do you like cats?"
ask = gets
def ask(n)
if ask == yes
return "I do too"
end
if ask == no
return "Dogs are better"
end
end
puts "#{ask(n)}"
Error message is :
pracif.rb:15:in <main>': undefined local variable or methodn' for
main: Object (NameError)
Here's a script that would work for you :
puts "Do you like cats?"
answer = gets
def ask(n)
if n == 'yes'
return "I do too"
end
if n == 'no'
return "Dogs are better"
end
end
puts ask(answer.downcase.chomp)
Explaination
As the error said you were trying to pass in a variable n which was not defined
Secondly you have a method name ask same as variable name. I've renamed the variable to answer instead
Thirdly, enclose yes and no in quotes
And finally, since you are using gets a \n gets appended like yes\n so none of your conditions would match. So i've used chomp to remove \n. And also used downcase to make input case insensitive.
EDIT
As mentioned by #Jordan in the comments, there is no reason to use string interpolation for the puts statement. So it's enough to call the method directly.
There are a bunch of issues with your code. Try something more like:
def reply(response)
return 'I do too' if response == 'yes'
return 'Dogs are better' if response == 'no'
'Invalid response!'
end
puts 'Do you like cats?'
response = gets().chomp()
puts reply(response)
Pay attention to the variable names. If you keep them descriptive, it is easier to spot mistakes.
Your script has no n local variable defined that you are passing to your ask(n) method at the end.
Rename your ask variable that your script gets from user to answer for example and pass it to your ask method at the end like so:
Updated code to fix other problem I did not see in the first run.
puts "Do you like cats?"
answer = gets.chomp
def ask(n)
(n == 'yes') ? "I do too" : "Dogs are better"
end
puts "#{ask(answer)}"
In Learn Ruby The Hard Way book on exercise 19, it says one should take the provided function:
def cheese_and_crackers(cheese_count, boxes_of_crackers)
puts "You have #{cheese_count} cheeses!"
puts "You have #{boxes_of_crackers} boxes of crackers!"
puts "Man that's enough for a party!"
puts "Get a blanket.\n"
end
and explore different approaches with it. I tried to explore the function's arguments and write a text with it:
file = ARGV.first
puts "Let's make a test?"
puts "Does the output file exist? #{File.exist?(arquivo)} "
puts "Ready, hit RETURN to continue, CTRL-C to abort."
$stdin.gets
def success(price, recipe)
puts """Text goes on like this:
In order to become a coder, You must dedicate yourself.\n
For that, you must pay a price, such as #{price}\n
Becoming a coder also requires #{recipe}\n"""
end
puts "What is the price to pay in order to become a coder?"
price = $stdin.gets
puts "What are the fundamental components in order to become a coder?"
recipe = $stdin.gets
coder = success(price, recipe)
motivational = File.open(file, 'w')
motivational.write(coder)
puts "Read this every day."
But I can't seem to make it write the function into a new test.txt file. The test.txt file comes out empty.
When calling puts, you're writing to stdout, but the return value will be empty.
Change this:
def success(price, recipe)
return """Text goes on like this:
In order to become a coder, You must dedicate yourself.\n
For that, you must pay a price, such as #{price}\n
Becoming a coder also requires #{recipe}\n"""
end
Then also:
motivational.close()
EDIT: Here's an extended explanation: when calling puts, you're just writing the string to stdout, which is the default output for programs. Methods (functions) can have a return value. For your success method, you need to return the string, so that you can write it in your file. If you call puts instead of return, the success method will not return any value, therefore leaving the file empty.
As for the close() call, it is advisable to close the file stream before your script ends.
Take a look at these references for more information:
https://www.ruby-lang.org/en/documentation/quickstart/2/
http://ruby-doc.org/core-2.2.3/IO.html
I am trying to determine the best way to loop through a case statement until a user provides a certain input (in this case, exit).
So far, my code works with a while loop, but it seems a little redundant when I have input = gets.chomp over and over.
Here's a bit of abbreviated code:
input = gets.chomp
while input.downcase != 'exit'
case input.downcase
when 'help'
puts "Available commands are..."
input = gets.chomp
#more when statements go here...
else
puts "That is not a valid command. Type 'HELP' for available commands."
input = gets.chomp
end
end
puts "Goodbye!"
I'd write it like:
loop do
input = gets.chomp.downcase
case input
when 'help'
puts "Available commands are..."
# more when statements go here...
when 'exit'
break
else
puts "That is not a valid command. Type 'HELP' for available commands."
end
end
puts "Goodbye!"
A loop is designed for this sort of case, where you just want to loop cleanly, and then eventually break out on some condition.
For ultimate clarity in what the code is doing, I'd put the exit immediately after reading the input, instead of being embedded in the case statements. It's a minor thing, but is useful to remember if you're coding and others have to help maintain it:
loop do
input = gets.chomp.downcase
break if input == 'exit'
case input
when 'help'
puts "Available commands are..."
# more when statements go here...
else
puts "That is not a valid command. Type 'HELP' for available commands."
end
end
puts "Goodbye!"
Why don't you change the while to:
while (input = gets.chomp.downcase) != 'exit'
Note that this also means that instead of using case input.downcase, you can use case input, as it has already been made lowercase.
edit: my roots in C betray me...
As mentioned in the comments, this is not a particularly "ruby-esque" solution. It also causes a stack trace when gets returns nil. You might prefer to split it into two lines:
while (input = gets)
input = input.chomp.downcase
break if input == 'exit'
case input
# when statements
else
puts "That is not a valid command. Type 'HELP' for available commands."
end
end
I separated the "exit" from the case criteria for a couple of reasons:
It was part of the loop logic in the question, so it's (arguably) more readable to keep it separate from the other cases.
I didn't realise that break behaves differently in Ruby case statements to other languages that I am more familiar with, so I didn't think it would do what you wanted.
You could equally well do this:
while (input = gets)
case input.chomp.downcase
when 'exit'
break
# other when statements
else
puts "That is not a valid command. Type 'HELP' for available commands."
end
end
edit: I am delighted to hear that like Perl, Ruby also has the $_ variable, to which the value of gets will be assigned:
while gets
case $_.chomp.downcase
when 'exit'
break
# other when statements
else
puts "That is not a valid command. Type 'HELP' for available commands."
end
end
You can even get rid of input by exiting the loop with break instead of checking the result in the while condition
while true
case gets.chomp.downcase
when 'exit'
break
when 'help'
# stuff
else
# other stuff
end
end
I'm trying to figure out why the following code does not work in a here-doc string eval:
script = <<FILE
def i_feel(&block)
block_given? ? "I feel #{ yield } :D" : "I don't know how I feel :/"
end
i_feel
# => "I don't know how I feel :/"
i_feel { 'great' }
# => "I feel great :D"
FILE
puts script
`<main>': no block given (yield) (LocalJumpError)
I know that part of the reason is the string interpolation. But how do I make it work? Try it without the here-doc first and see if it works?
You can avoid interpolation in a heredoc by surrounding the identifier with ':
script = <<'FILE'
something with #{interpolation} like syntax.
FILE
puts script
This will just print out the literal something with #{interpolation} like syntax. Without the ' around FILE you would probably get an error (if interpolation was defined you wouldn’t).
You can also use ` (backticks) to execute the contents of the heredoc:
s = <<`SCRIPT`
echo foo
echo bar
SCRIPT
s will now contain the result of executing the heredoc – in this case the string "foo\nbar\n".
I think that I just figured it out.
script = <<FILE
def i_feel(&block)
block_given? ? "I feel yield :D" : "I don't know how I feel :/"
end
i_feel
# => "I don't know how I feel :/"
i_feel { 'great' }
# => "I feel great :D"
FILE
puts script
Just remove the string interpolation brackets and here doc prints it just fine without them. I think I forgot about setting it up to interpolate is all. Oops! I'll get back to you all on this when I can.
Maybe now I can get something new from it. At least the error went away.
That will stop distracting me.
Here's the answer and a little more about what my intended purpose is. You want to see what you just ran so this is the complete version.
script = <<FILE
def how_i_feel
block_given? ? "I feel \#{ yield }." : "I don't know how I feel :/."
end
#{ def how_i_feel
block_given? ? "I feel #{ yield }." : "I don't know how I feel :/."
end }
how_i_feel
#{ how_i_feel }
how_i_feel { 'great :D' }
#{ how_i_feel { 'great :D' } }
FILE
puts script
What Victor said was right.
Here doc includes scope also.
In this case it is the interpolation of the interpolation.
Sounds a little confusing but just look at what level those brackets go to.
Notice also that we have to escape the original #{ yield } less it try to evaluate it.
That was what caused all the trouble in the first place.
Hope this helps.
And by the way this is just copied from https://github.com/JoshCheek/ruby-kickstart/blob/kevin_challenge/cheatsheets/blocks_procs_and_lambdas.rb
From that you can see that you don't need the &block parameter.