| /* |
| ** 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 |
| } |
| } |