Найти и заменить слова в каталоге текстовых файлов - PullRequest
1 голос
/ 23 июля 2011

Я нахожусь на завершающей стадии разработки мода для Инди-игры Гном Крепость .Последнее, что требуется перед тем, как мод заработает, - это просмотреть и изменить RAW Dwarf Fortress - два десятка или около того текстовых файла, которые содержат информацию о сотнях существ, населяющих игру.

Сколько это стоитс технической точки зрения, просматривает каталог текстовых файлов и в основном выполняет операцию «Найти и заменить», чтобы изменить каждую строку.

Большинство моих опытов программирования связаны с объектно-ориентированными языками - C # и Java.и некоторый опыт работы с Ассемблером и С. Однако ни один из этих языков не кажется оптимальным для такого рода задач.

Единственное преимущество в том, что в противном случае было бы очень простой заменой, состоит в том, что из-за способа, которым ГномRAW крепости написаны, я не буду знать, если мне нужно заменить строку, пока дальше вниз по текстовому файлу.Ниже приведен сокращенный пример сценария.

[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]

Программа, которую я хочу написать, должна иметь возможность прочитать строку [MULTIPLY_VALUE: X], а затем вернуться и заменить две строки, содержащие [BODY_DETAIL_PLAN:Z] с [BODY_DETAIL_PLAN: Y], где Y изменяется в зависимости от значения чтения X.

Я могу гарантировать две вещи:

  • При большинство одинСтрока [MULTIPLY_VALUE: X] появится между [CREATURE: A] и [CREATURE: B] или [CREATURE: Z] и концом файла.
  • Строка [MULTIPLY_VALUE: X] всегда будет приходить после строки [BODY_DETAIL_PLAN: Z], если она присутствует на этом существе.

Исходя из моего опыта кодирования, наиболее близкая вещь, которую я имею к жизнеспособной идее, - это написатьпрограмма на C для чтения файла, используя указатели для «сохранения» местоположения строк чтения и изменения их, когда программа чтения файлов обнаруживает запуск нового RAW.

Однако , который кажется мне неэлегантным, и сталкивается с проблемой того, что у меня нет опыта во внедрении функции поиска / замены в C (или любом другом языке).

Есть ли какой-нибудь более простой способ выполнить эту монотонную задачу, проходящую вручную по каждому текстовому файлу?Я полностью готов выучить новый язык программирования, но я точно не знаю, какой язык будет легче всего справиться с этой ситуацией.

Предложения?

Ответы [ 2 ]

1 голос
/ 23 июля 2011

Хорошо ... причина, по которой я задавал вопросы раньше, заключается в том, что я хотел знать, важен ли контекст заменяемых строк. Так как, если контекст НЕ важен, тогда вся рекурсивная замена будет в основном однострочной программой.

Исходя из ваших ответов, я предполагаю, что контекст должен быть принят во внимание. Итак, вот упрощенный пример на Ruby. Просто в качестве примера, чтобы вы могли видеть, как это работает. Код немного многословен, чтобы помочь вам лучше понять его. Вы можете использовать его как базу и работать оттуда.

Программа работает следующим образом - допустим, у вас есть файл данных data.txt примерно так:

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

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

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

Вы запускаете программу:

ruby replace.rb data.txt

И в итоге вы получите data.txt.bak с исходными данными и замененным data.txt, который выглядит следующим образом:

[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]

Программа 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 - это интересный язык для программирования и отличное дополнение к вашему «инструментальному поясу». Поэтому, возможно, вам стоит взглянуть на это.

0 голосов
/ 23 июля 2011

использовать http://www.harddisksearch.com/ ..

Будет кусок пирога.

...