This question already has answers here:
Don't understand Ruby ljust/rjust/center methods
(2 answers)
Closed 5 years ago.
I'm using Ruby 2.4. HOw do I add an arbitrary amount of spaces to the end of my string? I thought it was ljust but
2.4.0 :003 > line = "abcdef"
=> "abcdef"
2.4.0 :004 > line = line.ljust(4, " ")
=> "abcdef"
Notice my string is unchanged. What am I doing wrong?
The integer to ljust() must be larger than the length of the string, or nothing will be appended. Since line is six chars, I believe you want:
line = "abcdef"
line = line.ljust(10, " ")
That'll add four spaces after the six characters already present in the string.
You could likely also do something along the lines of:
line = line.ljust(line.length + 4, " ")
You can add a multiple of a spaces:
line = "abcdef"
line + ' '*5
#=> "abcdef "
line
#=> "abcdef"
Or use concat which modifies the string.
line.concat(' '*5)
#=> "abcdef "
line
#=> "abcdef "
Related
I would like the following sub-string
1100110011110000
from
foo = "bar9-9 '11001100 11110000 A'A\n"
I have so far used the below, which yields
puts foo.split(',').map!(&:strip)[0].gsub(/\D/, '')
>> 991100110011110000
Getting rid of the 2 leading 9's is not too difficult in this scenario, but I would like a general solution which grabs numbers only within the ' ' single quotes
You can find the quoted part first with scan and then remove non-digits:
> results = "bar9-9 '11001100 11110000 A'A\n".scan(/'[^']*'/).map{|m| m.gsub(/\D/, '')}
# => ["1100110011110000"]
> results[0]
# => "1100110011110000"
The zeros and ones within the quoted string can be extracted using String#gsub with a regular expression, as opposed to methods that convert the string to an array of strings, modify the array and converted it back to a string. Here are three ways of doing that.
str ="bar9-9 '11001100 11110000 A'A\n"
#1: Extract the substring of interest and then remove characters other than zero and one
def extract(str)
str[str.index("'")+1, str.rindex("'")-1].gsub(/[^01]/,'')
end
extract str
#=> "1100110011110000"
#2 Use a flag to indicate when zeroes and ones are to be kept
def extract(str)
found = false
str.gsub(/./m) do |c|
found = !found if c == "'"
(found && (c =~ /[01]/)) ? c : ''
end
end
extract str
#=> "1100110011110000"
Here the regular expression requires the m modifier (to enable multiline mode) in order to convert the newline character to an empty string. (One could alternatively write str.chomp.gsub(/./)....)
Notice that this second method works when there are multiple single-quoted substrings.
extract "bar9-9 '11001100 11110000 A'A'10x1y'\n"
#=> "1100110011110000101"
#3 Use the flip-flop operator (variant of #2)
def extract(str)
str.gsub(/./m) do |c|
next '' if (c=="'") .. (c=="'")
c =~ /[01]/ ? c : ''
end
end
extract str
#=> "1100110011110000"
extract "bar9-9 '11001100 11110000 A'A'10x1y'\n"
#=> "1100110011110000101"
foo.slice(/'.*?'/).scan(/\d+/).join
#=> "1100110011110000"
This question already has answers here:
Best way to escape and unescape strings in Ruby?
(7 answers)
Closed 5 years ago.
How to convert a string with special characters escaped to the actual special chars?
For example, if I have this:
s = "hello\\nworld"
The output of puts is naturally this:
> puts s
hello\nworld
But how do I transform it into this?
hello
world
In other words, is there any function to unescape backslashed characters?
Your best bet is to do some string replacements.
s = "hello\\nworld"
puts s.gsub("\\n", "\n")
# >> hello
# >> world
The downside of this approach is that you have to explicitly list/process all special chars you need to unescape.
You interpolate \ by \\ ,
use one backslash instead of two:
s = "hello\nworld"
puts s
#=> hello
world
If your string is from a trusted source, you can use eval:
s = "hello\\nworld"
eval("\"#{s}\"") # => "hello\nworld"
Note that this allows arbitrary code execution:
s = "\"; loop { }; \""
eval("\"#{s}\"") # => infinite loop
Also this doesn't work for input like s = "\"".
I am trying to count the characters in a text file excluding white spaces. My thought was to use scan; however, the tutorial I am reading uses gsub. There is a difference in output between the two, and I was wondering why. Here are the two code blocks; the gsub version is the one that's giving me the correct output:
total_characters_nospaces = text.gsub(/\s+/, '').length
puts "#{total_characters_nospaces} characters excluding spaces."
And the other one:
chars = 0
totes_chars_no = text.scan(/\w/){|everything| chars += 1 }
puts chars
The opposite of \s is not \w - it is \S.
\w is equivalent to [a-zA-Z0-9_]. It does not include many other characters such as punctuation.
\S is the exact opposite of \s - it includes any character that is not whitespace.
Now that your question has been answered, here are a couple other ways you could do it:
s = "now is the time for all good"
s.count "^\s" # => 22
s.each_char.reduce(0) { |count, c| count + (c =~ /\S/ ? 1 : 0) } # => 22
I have a CSV-file delimited by colons, but it contains text-fields wrapped in quotes, which themselves contain several colons.
I would like a simple solution for getting the data fields, but eg. in ruby the split method splits on every colon.
Is there a regex which matches all colons, except those wrapped in quotes?
Given:
str = 'foo:bar:"jim:jam":jar'
You can do this:
a = str.scan( /([^":]+)|"([^"]+)"/ ).flatten.compact
p a
#=> ["foo", "bar", "jim:jam", "jar"]
Or you can do this:
a = []
str.scan( /([^":]+)|"([^"]+)"/ ){ a << ($1 || $2) }
p a
#=> ["foo", "bar", "jim:jam", "jar"]
Those regex say to find either
One or more characters that are not a-quote-or-a-colon, or
A quote, followed by one or more characters that are not a quote, followed by a quote.
Just use http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html
you can split on double quotes instead of colons
>> str = 'foo:bar:"jim:jam":jar'
=> "foo:bar:\"jim:jam\":jar"
>> str.split("\"").each_with_index do |x,y|
?> puts y%2==0 ? x.split(":") : x
>> end
foo
bar
jim:jam
jar
First attempt was so bad, revised the entire thing. This is my regex solution:
GETS LAST delimeter field ':' = :last
Trims: /(?:^\s*:|:|^)\s*(".*?"|.*?)(?=\s*(?:\:|$))/
No-trim: /(?:(?<!^):|^)(\s*".*?"\s*|.*?)(?=\:|$)/
------------------
GETS FIRST AND LAST delimeter fields ':' = first:last
Trims: /(?:^|:)\s*(".*?"|(?<!^).*?|)(?=\s*(?:\:|$))/
No trim: /(?:^|:)(\s*".*?"\s*|\s*(?<!^).*?|)(?=\:|$)/
And yes, its not as easy as one thinks ..
In Ruby language, how can I get the number of lines in a string?
There is a lines method for strings which returns an Enumerator. Call count on the enumerator.
str = "Hello\nWorld"
str.lines.count # 2
str = "Hello\nWorld\n" # trailing newline is ignored
str.lines.count # 2
The lines method was introduced in Ruby 1.8.7. If you're using an older version, checkout the answers by #mipadi and #Greg.
One way would be to count the number of line endings (\n or \r\n, depending on the string), the caveat being that if the string does not end in a new line, you'll have to make sure to add one to your count. You could do so with the following:
c = my_string.count("\n")
c += 1 unless c[-1,1] == "\n"
You could also just loop through the string and count the lines:
c = 0
my_string.each { |line| c += 1 }
Continuing with that solution, you could get really fancy and use inject:
c = my_string.each.inject(0) { |count, line| count += 1 }
string".split("\n").size works nicely. I like that it ignores trailing new-lines if they don't contain content.
"Hello\nWorld\n".split("\n") # => ["Hello", "World"]
"hello\nworld\nfoo bar\n\n".split("\n").size # => 3
That might not be what you want, so use lines() as #Anurag suggested instead if you need to honor all new-lines.
"hello\nworld\nfoo bar\n\n".lines.count # => 4
"hello\nworld\nfoo bar\n\n".chomp.split("\n",-1).size # => 4
String#chomp gets rid of an end of line if it exists, and the -1 allows empty strings.
given a file object (here, in rails)
file = File.open(File.join(Rails.root, 'lib', 'file.json'))
file.readlines.count
returns the number of lines
IO#readlines performs a split method on strings (IOStrings in this case) using newlines as the separator
This will not count blank lines:
string.split("\n").select{ |line| line != "" }.size