Replace string characters with a single comma - ruby

I want to remove unwanted symbols from this string:
myString = String.new("##106#107#Hello##106#World##")
and separate each word with a comma. The desired result is:
"Hello, World"
Any ideas on how to achieve my desired result? What I tried is this:
myString.gsub!(/[##0123456789]/, ',')
print myString + "\n"
# => ",,,,,,,,,,Hello,,,,,,World,,"

There are a couple of ways:
myString.scan(/[a-zA-Z]+/).join(', ')
=> "Hello, World"

myString.gsub(/(\A)?[^a-zA-Z]+(\z)?/){$1 || $2 ? "" : ", "}
# => "Hello, World"

Related

Evaluate a string with indexed array as values

I would like to take a string that contains positional argument markers (not named), supply it with an array (not hash) of values, and have it evaluated.
The use case as an example would be somewhat like ARGV.
For example,
# given:
string = "echo $1 ; echo $#"
values = ["hello", "world"]
# expected result:
"echo hello ; echo hello world"
The below function is the best I could come up with:
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
# Create a variable that can replace $# with all arguments, and quote
# arguments that had "more than one word" originally
all_arguments = arguments.map{|a| a =~ /\s/ ? "\"#{a}\"" : a}.join ' '
# Replace all $1 - $9 with their respective argument ($1 ==> arguments[0])
string.gsub!(/\$(\d)/) { arguments[$1.to_i - 1] }
# Replace $# or $* with all arguments
string.gsub!(/\$[*|#]/, all_arguments)
return string
end
And it seems to me like it can and should be simpler.
I was hoping to find something that is closer to the Kernel.sprintf method of doing things - like "string with %{marker}" % {marker: 'value'}
So, although this issue is almost solved for me (I think), I would love to know if there is something I missed that can make it more elegant.
It seems like you're trying to reproduce Bash-style variable expansion, which is an extremely complex problem. At the very least, though, you can simplify your code in two ways:
Use Kernel.sprintf's built in positional argument feature. The below code does this by substituting e.g. $1 with the sprintf equivalent %1$s.
Use Shellwords from the standard library to escape arguments with spaces etc.
require 'shellwords'
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
tmpl = string.gsub(/\$(\d+)/, '%\1$s')
(tmpl % arguments).gsub(/\$[*#]/, arguments.shelljoin)
end
string = "echo $1 ; echo $#"
values = ["hello", "world"]
puts evaluate_args(string, values)
# => echo hello ; echo hello world
If you didn't have the $* requirement I'd suggest just dropping the Bash-like format and just using sprintf, since it covers everything else you mentioned. Even so, you could further simplify things by using sprintf formatting for everything else:
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
string.gsub('%#', arguments.shelljoin) % arguments
end
string = "echo %1$s ; echo %#"
values = ["hello", "world"]
puts evaluate_args(string, values)
# => echo hello ; echo hello world
Edit
If you want to use %{1} with sprintf you could turn the input array into a hash where the integer indexes are turned into symbol keys, e.g. ["hello", "world"] becomes { :"1" => "hello", :"2" => "world" }:
require "shellwords"
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
string % {
:* => arguments.shelljoin,
**arguments.map.with_index {|val,idx| [ :"#{idx + 1}", val ] }.to_h
}
end
string = "echo %{1} ; echo %{*}"
values = ["hello", "world"]
puts evaluate_args(string, values)
# => echo hello ; echo hello world
string = "echo $1 ; echo $# ; echo $2 ; echo $cat"
values = ["hello", "World War II"]
vals = values.map { |s| s.include?(' ') ? "\"#{s}\"" : s }
#=> ["hello", "\"World War II\""]
all_vals = vals.join(' ')
#=> "hello \"World War II\""
string.gsub(/\$\d+|\$[#*]/) { |s| s[/\$\d/] ? vals[s[1..-1].to_i-1] : all_vals }
#=> "echo hello ; echo hello \"World War II\" ; echo \"World War II\" ; echo $cat" $cat"

substitute characters but not the last one

I have a string for example like this:
str = 'TEST;NAME=1;TARGET_SOMETHING;PLATFORM_INTEL;'
Now I would like to substitute all ";" with "-D" and delete the last ";"
I'm doing it with:
str.gsub(/;/, ' -D').gsub(/^/, ' -D')
the second gsub is only to add the -D also to the beginn of line
Result:
-DTEST -DNAME=1 -DTARGET_SOMETHING -DPLATFORM_INTEL -D
How to tell Ruby not to output the last "-D" or to delete the last ";" in str?
Any suggestions to do it in the same line?
You can combine split and map for this.
irb(main):012:0> str.split(";").map {|i| "-D#{i}"}.join(" ")
=> "-DTEST -DNAME=1 -DTARGET_SOMETHING -DPLATFORM_INTEL"
elements= (str.gsub(/;/, ' -D').gsub(/^/, ' -D')).split(' ')
output will be:
["-DTEST", "-DNAME=1", "-DTARGET_SOMETHING", "-DPLATFORM_INTEL", "-D"]
then delete last element from an array:
elements.delete_at(elements.size-1)
output will be in elements variable
p elements
["-DTEST", "-DNAME=1", "-DTARGET_SOMETHING", "-DPLATFORM_INTEL"]

How to add escape sequence to String variables?

When adding one escape character to string and printing the output does not replace escape character in the output string
indent = '\t'
message = 'Hello there'
message = "#{indent} #{message}"
puts(message)
From the above code output printed is as below
\t Hello there
What is wrong with this code? What is the way to achieve the intended output?
You have to use " instead ' in:
indent = '\t'
Look:
irb(main):001:0> indent = '\t'
=> "\\t"
irb(main):002:0> indent = "\t"
=> "\t"

Extract string matching regex

I wanted to extract the value between "#" and ":" as well as after ":" within the following string:
str =
"this is some text
Text#7789347: 4444
some text
text # 7789348 : 666,555
some text
"
Output:
"7789347", " 4444"
"7789348", " 666,555"
I am using the following regex:
(\s)*[t|T][e|E][x|X][t|T](\s)*#(\s)*(\d)*(\s)*:.*
I can select the required field, but I don't know how to get the values.
In case you have to match only floating digits, you can use the /(?mi)^\s*\btext\b.*?#\s*(\d+(?:,\d+)?)\s*:\s*(\d+(?:,\d+)?)$/ regex:
str="""this is some text
Text#7789347: 4444
some text
text # 7789348 : 666,555
some text
"""
puts str.scan(/(?mi)^\s*\btext\b.*?#\s*(\d+(?:,\d+)?)\s*:\s*(\d+(?:,\d+)?)$/)
Output of the demo:
7789347
4444
7789348
666,555
You can scan it like this:
str.each_line{ |line|
a = line.scan(/#(.*):(.*)$/)
puts a[0].inspect if !a.empty?
}
# ["7789347", " 4444"]
# [" 7789348 ", " 666,555"]
To get the values you can use: #\s*(.*?)\s*:\s*(\d+(?:,\d+)*)
if line =~ /#\s*(.*?)\s*:\s*(\d+(?:,\d+)*)/
match1 = $~[1]
match2 = $~[2]
else
match = ""
end
Below Regex may help you:
#\s*(\d+)\s*:\s*([0-9,]*)
DEMO

Replacing escape quotes with just quotes in a string

So I'm having an issue replacing \" in a string.
My Objective:
Given a string, if there's an escaped quote in the string, replace it with just a quote
So for example:
"hello\"74" would be "hello"74"
simp"\"sons would be simp"sons
jump98" would be jump98"
I'm currently trying this: but obviously that doesn't work and messes everything up, any assistance would be awesome
str.replace "\\"", "\""
I guess you are being mistaken by how \ works. You can never define a string as
a = "hello"74"
Also escape character is used only while defining the variable its not part of the value. Eg:
a = "hello\"74"
# => "hello\"74"
puts a
# hello"74
However in-case my above assumption is incorrect following example should help you:
a = 'hello\"74'
# => "hello\\\"74"
puts a
# hello\"74
a.gsub!("\\","")
# => "hello\"74"
puts a
# hello"74
EDIT
The above gsub will replace all instances of \ however OP needs only to replace '" with ". Following should do the trick:
a.gsub!("\\\"","\"")
# => "hello\"74"
puts a
# hello"74
You can use gsub:
word = 'simp"\"sons';
print word.gsub(/\\"/, '"');
//=> simp""sons
I'm currently trying str.replace "\\"", "\"" but obviously that doesn't work and messes everything up, any assistance would be awesome
str.replace "\\"", "\"" doesn't work for two reasons:
It's the wrong method. String#replace replaces the entire string, you are looking for String#gsub.
"\\"" is incorrect: " starts the string, \\ is a backslash (correctly escaped) and " ends the string. The last " starts a new string.
You have to either escape the double quote:
puts "\\\"" #=> \"
Or use single quotes:
puts '\\"' #=> \"
Example:
content = <<-EOF
"hello\"74"
simp"\"sons
jump98"
EOF
puts content.gsub('\\"', '"')
Output:
"hello"74"
simp""sons
jump98"

Resources