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.
精彩评论