开发者

Find and Replace Words in a Directory of Text Files

I am in the final stages of developing a mod for the Indie Game Dwarf Fortress. The last thing required before the mod is in working order is to go through and alter the Dwarf Fortress RAWs -- two dozen or so text files that contain information about the hundreds of creatures populating the game.

What this amounts to from a technical perspective, is going through a directory of text files, and basically performing a "Find and Replace" operation to alter each line.

Most of my programming experiences are with object oriented languages - C# and Java, and some experience with Assembler and C. However, none of these languages seem optimal for this kind of task.

The one catch in what would otherwise be a very simple substituion, is that because of the way the Dwarf Fortress RAWs are written, I won't know if I need to replace the line until further down the text file. Below is an abbreviated example scenario.

[CREATURE:WOLF]
    ...
    [Many irrelevant lines of tokens]
    ...
[BODY_DETAIL_PLAN:STANDARD_MATERIALS]
[BODY_DETAIL_PLAN:STANDARD_TISSUES]
    ...
    [Many more irrelevant lines of tokens]
    ...
[MULTIPLY_VALUE:2]

The program I wish to write needs to be able to read through to the [MULTIPLY_VALUE:X] line and then go back and replace the two lines containing [BODY_DETAIL_PLAN:Z] with [BODY_DETAIL_PLAN:Y], where Y changes depending on the read value of X.

I can guarantee two things:

  • At most one [MU开发者_如何学编程LTIPLY_VALUE:X] line will appear between [CREATURE:A] and [CREATURE:B] or [CREATURE:Z] and the end of the file.
  • The [MULTIPLY_VALUE:X] line will always come after the [BODY_DETAIL_PLAN:Z] line, if it is present on that creature.

Based on the coding experience I have, the closest thing I have to a viable idea is writing a C program to read the file, using pointers to 'save' the location of the read lines and change them when the file reader detects the start of a new RAW.

However, that strikes me as inelegant, and runs into the trouble of me having no experience in implementing a find/replace function in C (or any language) in the first place.

Is there some easier way to accomplish this otherwise monotonous task of going through each text file by hand? I am totally willing to learn a new programming language, but I don't exactly know which language would be easiest to handle this situation.

Suggestions?


Ok..the reason I was asking the questions before is I wanted to know if the context of the lines to be replaced was important. Since if the context is NOT important then the whole recursive replace thing will be mostly a one-liner program.

Based on your answers I'm assuming that context needs to be taken into account. So with that here's a simplified example in Ruby. Just as an example so you can see how it works. The code is a bit verbose to help you understand it better. You could use it as a base and work from there.

The program works like this - let's say you have a data file data.txt like so:

[aaa]
[bbb]
[replace:a]
[replace:b]

[start_marker]
  [xxx]
  [replace:x]
  [replace:y]
  [yyy]
[end_marker]

[replace:c]
[replace:d]
[ccc]
[ddd]

You run the program:

ruby replace.rb data.txt

And you end up with data.txt.bak with the original data, and a replaced data.txt that looks like this:

[aaa]
[bbb]
[replace:a]
[replace:b]

[start_marker]
  [xxx]
  [replace:x was replaced!]
  [replace:y was replaced!]
  [yyy]
[end_marker]

[replace:c]
[replace:d]
[ccc]
[ddd]

The program replace.rb:

require 'rubygems'
require 'ftools'         # File.move
require 'extensions/io'  # File.writelines

file  = ARGV.shift
lines = File.open(file).readlines

replace_these  = Array.new
within_section = false

# Loop until we hit start_marker, then store potential
# lines until we hit end_marker, then fix the lines
lines.each { |line|
  within_section = true if line.match /\[start_marker\]/

  if line.match /\[end_marker\]/
    within_section = false

    replace_these.each { |line|
      # Do something clever...
      line.gsub!(/:(\w+)/, ':\1 was replaced!')
    }

    replace_these = Array.new
  end

  next if !within_section

  # Store lines to be replaced for later processing
  replace_these << line if line.match /\[replace:.*\]/
}

# Make a backup of the original file
File.move(file, "#{file}.bak")

# Overwrite the original with the new data
File.writelines(file, lines)

Ruby is a fun language to program in, and a nice addition to have in your "tool belt". So might be something you want to take a look at.


use http://www.harddisksearch.com/ ..

Would be piece of cake.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜