224 lines
7.1 KiB
C#
224 lines
7.1 KiB
C#
/*
|
|
** 2016 February 26
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains C# code to perform regular expression replacements
|
|
** using the standard input and output channels.
|
|
*/
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.RegularExpressions;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#region Assembly Metadata
|
|
[assembly: AssemblyTitle("Replace Tool")]
|
|
[assembly: AssemblyDescription("Replace text using standard input/output.")]
|
|
[assembly: AssemblyCompany("SQLite Development Team")]
|
|
[assembly: AssemblyProduct("SQLite")]
|
|
[assembly: AssemblyCopyright("Public Domain")]
|
|
[assembly: ComVisible(false)]
|
|
[assembly: Guid("95a0513f-8863-48cd-a76f-cb80868cb578")]
|
|
[assembly: AssemblyVersion("1.0.*")]
|
|
|
|
#if DEBUG
|
|
[assembly: AssemblyConfiguration("Debug")]
|
|
#else
|
|
[assembly: AssemblyConfiguration("Release")]
|
|
#endif
|
|
#endregion
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace Replace
|
|
{
|
|
/// <summary>
|
|
/// This enumeration is used to represent all the possible exit codes from
|
|
/// this tool.
|
|
/// </summary>
|
|
internal enum ExitCode
|
|
{
|
|
/// <summary>
|
|
/// The file download was a success.
|
|
/// </summary>
|
|
Success = 0,
|
|
|
|
/// <summary>
|
|
/// The command line arguments are missing (i.e. null). Generally,
|
|
/// this should not happen.
|
|
/// </summary>
|
|
MissingArgs = 1,
|
|
|
|
/// <summary>
|
|
/// The wrong number of command line arguments was supplied.
|
|
/// </summary>
|
|
WrongNumArgs = 2,
|
|
|
|
/// <summary>
|
|
/// The "matchingOnly" flag could not be converted to a value of the
|
|
/// <see cref="Boolean"/> type.
|
|
/// </summary>
|
|
BadMatchingOnlyFlag = 3,
|
|
|
|
/// <summary>
|
|
/// An exception was caught in <see cref="Main" />. Generally, this
|
|
/// should not happen.
|
|
/// </summary>
|
|
Exception = 4
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
internal static class Replace
|
|
{
|
|
#region Private Support Methods
|
|
/// <summary>
|
|
/// This method displays an error message to the console and/or
|
|
/// displays the command line usage information for this tool.
|
|
/// </summary>
|
|
/// <param name="message">
|
|
/// The error message to display, if any.
|
|
/// </param>
|
|
/// <param name="usage">
|
|
/// Non-zero to display the command line usage information.
|
|
/// </param>
|
|
private static void Error(
|
|
string message,
|
|
bool usage
|
|
)
|
|
{
|
|
if (message != null)
|
|
Console.WriteLine(message);
|
|
|
|
string fileName = Path.GetFileName(
|
|
Process.GetCurrentProcess().MainModule.FileName);
|
|
|
|
Console.WriteLine(String.Format(
|
|
"usage: {0} <regExPattern> <regExSubSpec> <matchingOnly>",
|
|
fileName));
|
|
}
|
|
#endregion
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
#region Program Entry Point
|
|
/// <summary>
|
|
/// This is the entry-point for this tool. It handles processing the
|
|
/// command line arguments, reading from the standard input channel,
|
|
/// replacing any matching lines of text, and writing to the standard
|
|
/// output channel.
|
|
/// </summary>
|
|
/// <param name="args">
|
|
/// The command line arguments.
|
|
/// </param>
|
|
/// <returns>
|
|
/// Zero upon success; non-zero on failure. This will be one of the
|
|
/// values from the <see cref="ExitCode" /> enumeration.
|
|
/// </returns>
|
|
private static int Main(
|
|
string[] args
|
|
)
|
|
{
|
|
//
|
|
// NOTE: Sanity check the command line arguments.
|
|
//
|
|
if (args == null)
|
|
{
|
|
Error(null, true);
|
|
return (int)ExitCode.MissingArgs;
|
|
}
|
|
|
|
if (args.Length != 3)
|
|
{
|
|
Error(null, true);
|
|
return (int)ExitCode.WrongNumArgs;
|
|
}
|
|
|
|
try
|
|
{
|
|
//
|
|
// NOTE: Create a regular expression from the first command
|
|
// line argument. Then, grab the replacement string,
|
|
// which is the second argument.
|
|
//
|
|
Regex regEx = new Regex(args[0]);
|
|
string replacement = args[1];
|
|
|
|
//
|
|
// NOTE: Attempt to convert the third argument to a boolean.
|
|
//
|
|
bool matchingOnly;
|
|
|
|
if (!bool.TryParse(args[2], out matchingOnly))
|
|
{
|
|
Error(null, true);
|
|
return (int)ExitCode.BadMatchingOnlyFlag;
|
|
}
|
|
|
|
//
|
|
// NOTE: Grab the standard input and output channels from the
|
|
// console.
|
|
//
|
|
TextReader inputTextReader = Console.In;
|
|
TextWriter outputTextWriter = Console.Out;
|
|
|
|
//
|
|
// NOTE: Loop until end-of-file is hit on the standard input
|
|
// stream.
|
|
//
|
|
while (true)
|
|
{
|
|
//
|
|
// NOTE: Read a line from the standard input channel. If
|
|
// null is returned here, there is no more input and
|
|
// we are done.
|
|
//
|
|
string inputLine = inputTextReader.ReadLine();
|
|
|
|
if (inputLine == null)
|
|
break;
|
|
|
|
//
|
|
// NOTE: Perform regular expression replacements on this
|
|
// line, if any. Then, write the modified line to
|
|
// the standard output channel.
|
|
//
|
|
string outputLine = regEx.Replace(inputLine, replacement);
|
|
|
|
if (!matchingOnly || !String.Equals(
|
|
inputLine, outputLine, StringComparison.Ordinal))
|
|
{
|
|
outputTextWriter.WriteLine(outputLine);
|
|
}
|
|
}
|
|
|
|
//
|
|
// NOTE: At this point, everything has succeeded.
|
|
//
|
|
return (int)ExitCode.Success;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//
|
|
// NOTE: An exception was caught. Report it via the console
|
|
// and return failure.
|
|
//
|
|
Error(e.ToString(), false);
|
|
return (int)ExitCode.Exception;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|