Hoi Gert,

So i've written a ReplaceRegex task based on the same task which exists
for ant: http://ant.apache.org/manual/OptionalTasks/replaceregexp.html.

Is it ok to commit and if so, can you commit this task to cvs?

Thanks,

Jeroen

p.s. Just drop the file in src/NAnt.Core/Tasks/ and it'll get built
automatically. I've tested it locally and both codepaths (byline=true/
false) work ok here on Linux with Mono.

On Sun, 2004-06-27 at 16:20 +0200, Gert Driesen wrote:
> Jeroen,
> 
> This is not possible right now, but a patch implementing filterchains has
> been submitted by Roger Dahlman (thanks !!!) which would allow this.
> 
> I just haven't had enough time to review the patch.
> 
> Gert
> 
> ----- Original Message -----
> From: "Jeroen Zwartepoorte" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Sunday, June 27, 2004 12:13 PM
> Subject: [Nant-users] using <regex> task on files
> 
> 
> > Hi,
> >
> > >From looking at the documentation, it seems the <regex> task is only to
> > be used for retrieving data from files, not to find & replace text in a
> > file. There doesn't seem to be a way to do a global replace (s/blah/bla/
> > g) for example.
> >
> > Is this correct? I need this kind of functionality for a configuration
> > file where the actual information required is only available at build
> > time. So i want to do a regex on the file:
> >
> > <copy file="node.plugin.in" tofile="node.plugin"/>
> > <regex pattern="s/@assembly@/${assemblyfile}/g" input="node.plugin"/>
> > <move file="node.plugin" todir="${plugin.dir}"/>
> >
> > Any ideas?
> >
> > Thanks,
> >
> > Jeroen
> >
> >
> >
> > -------------------------------------------------------
> > This SF.Net email sponsored by Black Hat Briefings & Training.
> > Attend Black Hat Briefings & Training, Las Vegas July 24-29 -
> > digital self defense, top technical experts, no vendor pitches,
> > unmatched networking opportunities. Visit www.blackhat.com
> > _______________________________________________
> > Nant-users mailing list
> > [EMAIL PROTECTED]
> > https://lists.sourceforge.net/lists/listinfo/nant-users
> >
> 
> 
> 
> -------------------------------------------------------
> This SF.Net email sponsored by Black Hat Briefings & Training.
> Attend Black Hat Briefings & Training, Las Vegas July 24-29 - 
> digital self defense, top technical experts, no vendor pitches, 
> unmatched networking opportunities. Visit www.blackhat.com
> _______________________________________________
> Nant-users mailing list
> [EMAIL PROTECTED]
> https://lists.sourceforge.net/lists/listinfo/nant-users
> 
// NAnt - A .NET build tool
// Copyright (C) 2001-2003 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Jeroen Zwartepoorte ([EMAIL PROTECTED])

using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;

using NAnt.Core.Attributes;

namespace NAnt.Core.Tasks {
    /// <summary>
    /// ReplaceRegex is a directory based task for replacing the occurrence of a
    /// given regular expression with a substitution pattern in a selected file
    /// or set of files. The output file is only written if it differs from the
    /// existing file. This prevents spurious rebuilds based on unchanged files
    /// which have been regenerated by this task.
    /// </summary>
    [TaskName("replaceregex")]
    public class ReplaceRegexTask : Task {
        #region Private Instance Fields

        private FileInfo _sourceFile;
        private string _match;
        private string _replace;
        private string _option = "";
        private bool _byline = false;
        private string _encoding;

        #endregion Private Instance Fields

        #region Public Instance Properties

        /// <summary>
        /// The file for which the regular expression should be replaced.
        /// Required if no nested &lt;fileset&gt; is used.
        /// </summary>
        [TaskAttribute("file", Required=false)]
        public FileInfo SourceFile {
            get { return _sourceFile;}
            set { _sourceFile = value; }
        }

        /// <summary>
        /// The regular expression pattern to match in the file(s).
        /// </summary>
        [TaskAttribute("match", Required=true)]
        [StringValidator(AllowEmpty=false)]
        public string MatchRegex {
            get { return _match;}
            set { _match = value; }
        }

        /// <summary>
        /// The substitution pattern to place in the file(s) in place of the
        /// regular expression.
        /// </summary>
        [TaskAttribute("replace", Required=true)]
        [StringValidator(AllowEmpty=false)]
        public string Replace {
            get { return _replace;}
            set { _replace = value; }
        }

        /// <summary>
        /// Allow Regex options to be passed in. A comma separated list of
        /// options to pass to the matchRegex engine. 
        /// </summary>
        [TaskAttribute("option", Required=false)]
        [StringValidator(AllowEmpty=true)]
        public string Option {
            get { return _option;}
            set { _option = value; }
        }

        /// <summary>
        /// Process the file(s) one line at a time, executing the replacement on
        /// one line at a time (<see langword="true" />/<see langword="false" />
        /// ). This is useful if you want to only replace the first occurence of
        /// a regular expression on each line, which is not easy to do when
        /// processing the file as a whole.
        /// Defaults to <see langword="false" />.
        /// </summary>
        [TaskAttribute("byline", Required=false)]
        [BooleanValidator()]
        public bool ByLine {
            get { return _byline; }
            set { _byline = value; }
        }

        #endregion Public Instance Properties

        #region Override implementation of Task

        /// <summary>
        /// Executes the task.
        /// </summary>
        protected override void ExecuteTask() {
            Regex matchRegex = null;
            RegexOptions opt = RegexOptions.None; // Regex object defaults to None
            if (Option.Length > 0) {
                string [] a = Option.Split(',');
                
                foreach (string s in a) {
                    try {
                        RegexOptions localopt =  (RegexOptions)Enum.Parse(typeof(RegexOptions), s );
                        opt |= localopt;
                    } catch (ArgumentException) {
                        string message = string.Format(CultureInfo.InvariantCulture, 
                            "'{0}' is not a valid matchRegex option. Valid values are: ", 
                            s);
                        foreach (object field in Enum.GetValues(typeof(RegexOptions) )) {
                            message += field.ToString() + ", ";
                        }

                        // strip last ,
                        message = message.Substring(0, message.Length - 2);
                        throw new BuildException(message, Location);
                    }
                }
            }

            matchRegex = new Regex(MatchRegex, opt);
            
            StreamReader reader = SourceFile.OpenText ();
            if (ByLine) {
                string tempFile = Path.GetTempFileName ();
                FileStream fs = new FileStream (tempFile, FileMode.Truncate, FileAccess.Write);
                StreamWriter sw = new StreamWriter (fs);
                bool modified = false;
                string line = null;
                while ((line = reader.ReadLine ()) != null) {
                    string dest = matchRegex.Replace (line, Replace);
                    if (!modified)
                        modified = !line.Equals (dest);
                    sw.WriteLine (dest);
                }
                reader.Close ();
                sw.Close ();
                
                if (modified)
                    File.Copy (tempFile, SourceFile.FullName, true);
                File.Delete (tempFile);
            } else {
                string source = reader.ReadToEnd ();
                reader.Close ();
                string dest = matchRegex.Replace (source, Replace);

                // Only overwrite the file if something was actually replaced.
                if (!source.Equals (dest)) {
                    FileStream fs = SourceFile.Open (FileMode.Truncate, FileAccess.Write);
                    StreamWriter sw = new StreamWriter (fs);
                    sw.Write (dest);
                    sw.Close ();
                }
            }
        }

        #endregion Override implementation of Task
    }
}

Reply via email to