I'm trying to read a file having string values, line by line and create respective folder/directory for every string value.
#require 'fileutils'
value=File.open('D:\\exercise\\list.txt').read
value.gsub!(/\r\n?/, "\n")
value.each_line do |line|
line.chomp
print "FOlder names:#{line}"
Dir.mkdir("D:\\exercise\\#{line}")
end
and I'm getting the below error:
read_folders_svn.rb:8:in `mkdir': Invalid argument - Australia (Errno::EINVAL)
from read_folders_svn.rb:8:in `block in <main>'
list.txt file's content below
Australia
USA
EUrope
Africa
ANtartica
I tried printing the values and its working fine, while creating the respective directories facing the above issue and even tried using fileutils (fileutils.mkdir) option but still the same issue.
Any suggestions please. Thanks
The error is in the line:
line.chomp
It strips the newline from the tail of line and returns a value that is ignored. It doesn't change the value of line. It still ends with "\n" and this is a character that is not allowed in file names on Windows. The code runs fine on Linux and creates directories whose names end in "\n".
The solution is also simple. Use #chomp! instead:
#require 'fileutils'
value=File.open('D:\\exercise\\list.txt').read
value.gsub!(/\r\n?/, "\n")
value.each_line do |line|
line.chomp!
print "FOlder names:#{line}"
Dir.mkdir("D:\\exercise\\#{line}")
end
(It might still produce errors, however, because of empty lines in the input).
Have you checked that the line doesn't contain extra characters? Where line.chomp! will solve your problem but line.strip! is probably the more robust variant, esp if you have windows line-endings of \r\n.
Difference between chomp and strip
String#chomp operates on the end of strings, while String#strip
operates on the start and end of strings. String#chomp takes an
optional 'record separator' argument, while String#strip takes no
arguments. If String#chomp is given no arguments it will remove
carriage returns characters from the end of the string being operated
on (\r, \n or \r\n). If String#chomp is passed a string as an
argument, that string is removed from the end of the string being
operated on. String#strip will remove leading and trailing null and
whitespace characters from the string being operated on.
"Cadel Evans".chomp(' Evans') # => "Cadel"
"Cadel Evans\r\n".chomp # => "Cadel Evans"
"\tRobbie McEwen\r\n".strip # => "Robbie McEwen"
Related
I'm trying to write a program which will detect if a file has \n or \r\n line endings and then fix them. I'm hoping to have the script output some messages to a console, but I'm running into trouble. I can't figure out how to print the line endings as literals.
Here is my method which checks for the line ending type:
def determine_line_ending(filename)
File.open(filename, 'r') do |file|
return file.readline[/\r?\n$/]
end
end
ending = determine_line_ending(ARGV.first)
Supposedly this method will return either \n or \r\n if it matches one of those patterns on the first line of the file.
I would like to then print to the console which ending type was detected but if I use puts ending then it just adds a line ending to the console. I know that if I used puts '\r\n' then it will print them literal, or if I use double quotes I just have to escape the backslashes. But I'm pretty new to Ruby and I'm having a hard time just finding a way to print my variable as a literal instead of a string.
If I'm understanding you well, you want to print the "\r" string if the line ending is \r and "\r\n" if \r\n.
In this case you can use the dump function is what you need:
puts ending.dump // => "\r" or "\r\n"
I would use method String#inspect:
s = "abc\n\rdef"
puts s
puts s.inspect
This is very handy method that is defined on all objects. You can print hashes, arrays, whatever.
I have a string which has been split anytime that a single line goes over 69 characters. In order to process it, I would like to restore it to how it was pre-split. A split line always starts with a forward slash character on the second and subsequent lines, which needs to be kept. Is there a nice Ruby way to do this?
# Split version
GTSS/230028GG/JUL15/LL:123456X3-0051234G4/DES/000G/57NM/57NM/095T
/002GTS////gts
# Required output
GTSS/230028GG/JUL15/LL:123456X3-0051234G4/DES/000G/57NM/57NM/095T/002GTS////gts
I'm happy matching a line that starts with the forward slash. What I don't know is how to remove the newline character from end of the previous line.
example.lines.each_with_index do |line, index|
if line.match(/^\/.+$/)
# what goes here?
end
end
I would use gsub:
string = "GTSS/230028GG/JUL15/LL:123456X3-0051234G4/DES/000G/57NM/57NM/095T\n/002GTS////gts"
string.gsub("\n/", '/')
#=> "GTSS/230028GG/JUL15/LL:123456X3-0051234G4/DES/000G/57NM/57NM/095T/002GTS////gts"
You can also use lstripit will remove all whitespace(space, newline...) from left:
example.lines.each_with_index do |line, index|
if line.match(/^\/.+$/)
line.lstrip
end
end
.strip will remove all whitespace(space, newline...) the whole string
Another way (but I like #spickermann's answer better):
str = "GTSS/230028GG/JUL15/LL:123456X3-0051234G4/DES/000G/57NM/57NM/095T
/002GTS////gts"
str.split("\n/").join("/")
#=> "GTSS/230028GG/JUL15/LL:123456X3-0051234G4/DES/000G/57NM/57NM/095T/002GTS////gts"
How do I get the first word from each line? Thanks to help from someone on Stack Overflow, I am working with the code below:
File.open("pastie.rb", "r") do |file|
while (line = file.gets)
next if (line[0,1] == " ")
labwords = line.split.first
print labwords.join(' ')
end
end
It extracts the first word from each line, but it has problems with spaces. I need help adjusting it. I need to use the first method, but I don't know how to use it.
If you want the first word from each line from a file:
first_words = File.read(file_name).lines.map { |l| l.split(/\s+/).first }
It's pretty simple. Let's break it apart:
File.read(file_name)
Reads the entire contents of the file and returns it as a string.
.lines
Splits a string by newline characters (\n) and returns an array of strings. Each string represents a "line."
.map { |l| ... }
Array#map calls the provided block passing in each item and taking the return value of the block to build a new array. Once Array#map finishes it returns the array containing new values. This allows you to transform the values. In the sample block here |l| is the block params portion meaning we're taking one argument and we'll reference it as l.
|l| l.split(/\s+/).first
This is the block internal, I've gone ahead and included the block params here too for completeness. Here we split the line by /\s+/. This is a regular expression, the \s means any whitespace (\t \n and space) and the + following it means one or more so \s+ means one or more whitespace character and of course, it will try to match as many consecutive whitespace characters as possible. Passing this to String#split will return an array of substrings that occur between the seperator given. Now, our separator was one or more whitespace so we should get everything between whitespace. If we had the string "A list of words" we'll get ["A", "list", "of", "words"] after the split call. It's very useful. Finally, we call .first which returns the first element of an array (in this case "the first word").
Now, in Ruby, the evaluated value of the last expression in a block is automatically returned so our first word is returned and given that this block is passed to map we should get an array of the first words from a file. To demonstrate, let's take the input (assuming our file contains):
This is line one
And line two here
Don't forget about line three
Line four is very board
Line five is the best
It all ends with line six
Running this through the line above we get:
["This", "And", "Don't", "Line", "Line", "It"]
Which is the first word from each line.
Consider this:
def first_words_from_file(file_name)
lines = File.readlines(file_name).reject(&:empty?)
lines.map do |line|
line.split.first
end
end
puts first_words_from_file('pastie.rb')
I need to match a line in an inputted text file string and wrap that captured line with a character for example.
For example imagine a text file as such:
test
foo
test
bar
I would like to use gsub to output:
XtestX
XfooX
XtestX
XbarX
I'm having trouble matching a line though. I've tried using regex starting with ^ and ending with $, but it doesn't seem to work. Any ideas?
I have a text file that has the following in it:
test
foo
test
bag
The text file is being read in as a command line argument.
So I got
string = IO.read(ARGV[0])
string = string.gsub(/^(test)$/,'X\1X')
puts string
It outputs the exact same thing that is in the text file.
If you're trying to match every line, then
gsub(/^.*$/, 'X\&X')
does the trick. If you only want to match certain lines, then replace .* with whatever you need.
Update:
Replacing your gsub with mine:
string = IO.read(ARGV[0])
string = string.gsub(/^.*$/, 'X\&X')
puts string
I get:
$ gsub.rb testfile
XtestX
XfooX
XtestX
XbarX
Update 2:
As per #CodeGnome, you might try adding chomp:
IO.readlines(ARGV[0]).each do |line|
puts "X#{line.chomp}X"
end
This works equally well for me. My understanding of ^ and $ in regular expressions was that chomping wouldn't be necessary, but maybe I'm wrong.
You can do it in one line like this:
IO.write(filepath, File.open(filepath) {|f| f.read.gsub(//<appId>\d+<\/appId>/, "<appId>42</appId>"/)})
IO.write truncates the given file by default, so if you read the text first, perform the regex String.gsub and return the resulting string using File.open in block mode, it will replace the file's content in one fell swoop.
I like the way this reads, but it can be written in multiple lines too of course:
IO.write(filepath, File.open(filepath) do |f|
f.read.gsub(//<appId>\d+<\/appId>/, "<appId>42</appId>"/)
end
)
If your file is input.txt, I'd do as following
File.open("input.txt") do |file|
file.lines.each do |line|
puts line.gsub(/^(.*)$/, 'X\1X')
end
end
(.*) allows to capture any characters and makes it a variable Regexp
\1 in the string replacement is that captured group
If you prefer to do it in one line on the whole content, you can do it as following
File.read("input.txt").gsub(/^(.*)$/, 'X\1X')
string.gsub(/^(matchline)$/, 'X\1X')
Uses a backreference (\1) to get the first capture group of the regex, and surround it with X
Example:
string = "test\nfoo\ntest\nbar"
string.gsub!(/^test$/, 'X\&X')
p string
=> "XtestX\nfoo\nXtestX\nbar"
Chomp Line Endings
Your lines probably have newline characters. You need to handle this one way or another. For example, this works fine for me:
$ ruby -ne 'puts "X#{$_.chomp}X"' /tmp/corpus
XtestX
XfooX
XtestX
XbarX
My ruby program is causing unwanted line breaks when calling a variable within a string.
The string is then printed to a text file. In this text file there are lot of unwanted line breaks.
Heres my code.
puts 'What is the 2nd Octet?'
second_octet = gets
puts 'What is the 3rd Octet?'
third_octet = gets
puts 'What is the vlan number?'
vlan_number = gets
vrf_number = <<-eos
123#{vlan_number}
eos
router_config = <<-eos
interface Bundle-Ether7.#{vlan_number}
description * #{description_name} *
mtu 9216
vrf #{vrf_number}
ipv4 address 10.#{second_octet}.#{third_octet}.252 255.255.255.0
eos
File.open(config, 'w') { |file| file.write(router_config) }`
I'm getting line breaks after I call the variables so there are gaps between lines, this is extremely annoying with the second_octet and third_octet variables as it splits the ip address across multiple lines.
Any help would be great! Thanks!
The string returned by gets includes the newline character (\n or \r\n) from the return/enter key. You need to do gets.chomp to take off the trailing newline, or gets.strip to get rid of leading and trailing whitespace. Either one should work in your case.