3

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.

sawa
  • 165,429
  • 45
  • 277
  • 381
Tommy
  • 965
  • 6
  • 13
  • 21
  • Welcome to Stack Overflow. Please improve your question by posting some [properly formatted](http://stackoverflow.com/editing-help) code you've applied to the problem, and all **relevant** error messages exactly as they appear. – Todd A. Jacobs Apr 13 '13 at 19:21
  • use word boundaries, i.e. `\b` see e.g. [this](http://stackoverflow.com/questions/2902004/ignoring-a-character-along-with-word-boundary-in-regex) – Fredrik Pihl Apr 13 '13 at 19:21

5 Answers5

5

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.

Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
5

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
)
Steve Benner
  • 1,679
  • 22
  • 26
2

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')
toch
  • 3,905
  • 2
  • 25
  • 34
1

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"
user21033168
  • 444
  • 1
  • 4
  • 13
  • I tried string.gsub(/^(test)$/,'X\1X') and it does not work. That is the problem I'm having? – Tommy Apr 13 '13 at 19:23
  • Perhaps you didn't include the !, at the end of gsub! to apply it in-place, try `p string.gsub(/^(test)$/, 'X\1X')` – user21033168 Apr 13 '13 at 19:27
  • My text file is read in through IO as an command line argument. Does it automatically put \n's in it? Because that regex does not work. – Tommy Apr 13 '13 at 19:30
  • If you are reading straight from argf maybe you need to use the .read method on it, this works: http://ideone.com/8jxyzT – user21033168 Apr 13 '13 at 19:35
  • The problem is with your string input, show us the exact string you are parsing to find the problem. (`print IO.read(ARGV[0])`) – user21033168 Apr 13 '13 at 19:44
  • Printing what you said displays exactly what I showed above test foo test bar on separate lines. – Tommy Apr 13 '13 at 19:50
  • Try this: `string.gsub(/^test\r?\n/, 'X\&X')` it recognizes carriage returns. – user21033168 Apr 13 '13 at 20:26
0

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
Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199