Friday, May 16, 2014

Short C++ program for text replacement in a text file

Below is a simple program for searching and replacing substrings in a text file. It is based on boost library, uses memory mapped file to use boost::regex_replace function, which supports working with streams. Process result stored to the temporary file, which will replace original file after processing completion.

Source code can be compiled on any platform supported by boost library, including Windows and Unix.


#include <iostream>
#include <fstream>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/regex.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>

using namespace std;
namespace po = boost::program_options;


void Replace(const string& inFilePath, const string& searchStr, const string& replacement)
{
 boost::iostreams::mapped_file istm(inFilePath.c_str());
 if (!istm.is_open())
  return;

 string tempFilePath = inFilePath + ".tmp";
 ofstream ostm(tempFilePath.c_str(), std::ios::out | std::ios::binary);
 if (!ostm.is_open()) {
  istm.close();
  return;
 }

 boost::regex regexp(searchStr);
 ostreambuf_iterator<char> it(ostm);
 boost::regex_replace(it, istm.begin(), istm.end(), regexp, replacement, boost::match_default | boost::format_all);
 
 istm.close();
 ostm.close();

 boost::filesystem::rename(tempFilePath, inFilePath);
}

int main(int argc, char *argv[])
{
 try {
  po::options_description optsDescription("Allowed commands");
  optsDescription.add_options()
   ("file",    po::value<string>(), "Path to the file to search in")
   ("find",    po::value<string>(), "What to search (substring or regular expression)")
   ("replace", po::value<string>()->default_value(""), "Substring to replace founded results");

  po::variables_map options;
  po::store(po::parse_command_line(argc, argv, optsDescription), options);

  po::notify(options);

  if (options.empty() || !options.count("file") || !options.count("find")) {
   cout << "Usage:" << endl;
   cout << "replace.exe --file=<path to file> --find=<search string> --replace=<replacement string>" << endl << endl;
   cout << optsDescription << endl;
   return 1;
  }

  Replace(options["file"].as<string>(), options["find"].as<string>(), options["replace"].as<string>());
 } catch (const exception& ex) {
  cout << "Execution failed: " << ex.what() << endl;
 }

 return 0;
}

No comments: