利用查找替換批處理(附完整源碼),進行高效重構


如果你需要在大量的代碼文件中修改某個地方,那么最高效的辦法就是使用正則進行批量處理。

 

下面介紹一個C#寫的查找替換處理程序。

我本人不喜歡太多的廢話,看過功能介紹,各位朋友感興趣,直接下載小源碼包或程序跑一通,就了解了。

主窗體


說明

目錄: 指定批處理操作的執行目錄。

子目錄:如果勾選,將處理所有子孫級目錄的文件。

文件篩選:與在Windows資源管理器上的搜索文件輸入的規則一樣。常用的就是星號加后綴名,比如*.cs 。

查找內容:可輸入正則表達式或者文本。

替換內容:可以輸入用於替換的文本。可以使用{N}占位,以進行后向引用操作。N序號從1開始,0表示匹配到的整個字符串。

正則:勾選,表示使用正則進行處理,否則使用文本進行處理。

 

處理結果窗體

 

雙擊選項可以打開文件

代碼

 主窗體代碼

 

View Code
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

namespace AFReplace
{
     public  partial  class FrmAFReplace : Form
    {
         private  string _basePath;
         private  string _findContent;
         private  string _filter;
         private  string _replacement;
         private  bool _replaceWithRegex;
         private  delegate  void DealDelegate( string workPath);

         private List<KeyValue> _lsDealFilesResult;
         ///   <summary>
        
///  查找或替換的操作委托
        
///   </summary>
         private DealDelegate _delWork;
         ///   <summary>
        
///  當前是否為替換的處理操作
        
///   </summary>
         private  bool _isReplaceDeal;


         public FrmAFReplace()
        {
            InitializeComponent();
            Icon = Properties.Resources.file_edit_2;
        }

         private  void btnReplace_Click( object sender, EventArgs e)
        {
            _isReplaceDeal =  true;
            _delWork = ReplaceContent;
            Work();
        }
         private  void Work()
        {
            _basePath = txtDirectory.Text;
             if (!Directory.Exists(_basePath))
            {
                tsslblMessage.Text =  " 路徑不存在 ";
                 return;
            }

            DirectoryInfo basePathInfo =  new DirectoryInfo(_basePath);

            _filter = txtFilter.Text;
             if ( string.IsNullOrEmpty(_filter))
            {
                tsslblMessage.Text =  " 文件篩選輸入為空 ";
                 return;
            }
            _findContent = txtFindContent.Text;
             if ( string.IsNullOrEmpty(_findContent))
            {
                tsslblMessage.Text =  " 查找內容輸入為空 ";
                 return;
            }
            _replacement = txtReplaceContent.Text;
            _replaceWithRegex = ckbReplaceWithRegex.Checked;
            _lsDealFilesResult =  new List<KeyValue>();
             if (ckbDirectoryItem.Checked)
            {
                 new Thread(() => WorkInDirectoryDeep(basePathInfo)).Start();
            }
             else
            {
                 new Thread(() => WorkInDirectory(basePathInfo)).Start();
            }
        }
         ///   <summary>
        
///  僅在指定目錄替換
        
///   </summary>
        
///   <param name="dirInfo"></param>
         private  void WorkInDirectory(DirectoryInfo dirInfo)
        {
            WorkByDirectoryInfo(dirInfo);
            WorkedAfter();
        }
         private  void WorkByDirectoryInfo(DirectoryInfo dirInfo)
        {
             if (dirInfo.Exists)
            {
                _delWork(dirInfo.FullName);
            }
        }
         private  void WorkedAfter()
        {
            ShowFindResult();
        }
         ///   <summary>
        
///  深入到子目錄替換
        
///   </summary>
        
///   <param name="dirInfo"></param>
         private  void WorkInDirectoryDeep(DirectoryInfo dirInfo)
        {
            WorkByDirectoryInfo(dirInfo);
            DirectoryInfo[] lsDirInfo = dirInfo.GetDirectories();
             if (lsDirInfo.Length >  0)
            {
                 foreach (DirectoryInfo info  in lsDirInfo)
                {
                    WorkInDirectory(info);
                }
            }
             else
            {
                ShowMessage( " 操作完成 ");
                WorkedAfter();
            }
        }
         ///   <summary>
        
///  在指定目錄查找指定文件,並替換,保存。
        
///   </summary>
        
///   <param name="workPath"></param>
         private  void ReplaceContent( string workPath)
        {
             string[] files = Directory.GetFiles(workPath, _filter);
             string value;
             foreach ( string file  in files)
            {
                 string content = File.ReadAllText(file);
                content = _replaceWithRegex ? Regex.Replace(content, _findContent, ReplaceDeal) : content.Replace(_findContent, _replacement);
                 byte[] buffer = Encoding.UTF8.GetBytes(content);
                 if ( new FileInfo(file).IsReadOnly)
                {
                    value =  " 文件只讀 >  " + Path.GetFileName(file);
                }
                 else
                {
                    File.Delete(file);

                     using (FileStream fs =  new FileStream(file, FileMode.Create, FileAccess.Write))
                    {
                        fs.Write(buffer,  0, buffer.Length);
                    }
                    value =  " 已處理 >  " + Path.GetFileName(file);


                }
                ShowMessage(value);
                _lsDealFilesResult.Add( new KeyValue(file, value));
            }
        }
         ///   <summary>
        
///  在指定目錄查找指定文件
        
///   </summary>
        
///   <param name="workPath"></param>
         private  void FindFiles( string workPath)
        {
             string[] files = Directory.GetFiles(workPath, _filter);
             foreach ( string file  in files)
            {
                 string content = File.ReadAllText(file);
                 bool isMatch = _replaceWithRegex ? Regex.IsMatch(content, _findContent) : content.Contains(_findContent);
                 if (isMatch)
                {
                    _lsDealFilesResult.Add( new KeyValue(file, file));
                }
            }
        }
         ///   <summary>
        
///  正則替換
        
///   </summary>
        
///   <param name="m"></param>
        
///   <returns></returns>
         private  string ReplaceDeal(Match m)
        {
             if (m.Success)
            {
                MatchCollection mc = Regex.Matches(_replacement,  @" {(?<value>\d+)} ");
                List< int> lsValueIndex =  new List< int>();
                 foreach (Match match  in mc)
                {

                     int iValueIndex =  int.Parse(match.Groups[ " value "].Value);
                     // 序號不可以大於查找到的集合數,總數為匹配()數+自身1
                     if (iValueIndex > m.Groups.Count)
                         throw  new Exception( " 替換的匹配數錯誤 ");

                     if (!lsValueIndex.Contains(iValueIndex))
                        lsValueIndex.Add(iValueIndex);
                }
                 return lsValueIndex.Aggregate(_replacement, (current, i) => current.Replace( " { " + i +  " } ", m.Groups[i].Value));
            }
             return  "";
        }
         private  void ShowMessage( string msg)
        {
             if (InvokeRequired)
            {
                Invoke( new MethodInvoker(() => ShowMessage(msg)));
            }
             else
            {
                tsslblMessage.Text = msg;
            }
        }
         private  void ShowFindResult()
        {
             if (InvokeRequired)
            {
                Invoke( new MethodInvoker(ShowFindResult));
            }
             else
            {
                 new FrmDealResult(_lsDealFilesResult, _isReplaceDeal ?  " 替換結果 " :  " 查找結果 ").Show();
            }
        }


         private  void lblAbout_Click( object sender, EventArgs e)
        {
            MessageBox.Show( " bug及建議提交,請聯系alifellod@163.com "" 查找替換 ", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

         private  void ckbReplaceWithRegex_CheckedChanged( object sender, EventArgs e)
        {
            toolTip1.SetToolTip(txtReplaceContent,
                                ckbReplaceWithRegex.Checked ?  " 可以使用{index}進行后向引用,{1}{2}={2}{1}。序號從1開始,0為匹配到的整個值。 " :  "");
        }

         private  void btnFind_Click( object sender, EventArgs e)
        {
            _isReplaceDeal =  false;
            _delWork = FindFiles;
            Work();
        }

         private  void txtDirectory_TextChanged( object sender, EventArgs e)
        {
            toolTip1.SetToolTip(txtDirectory, txtDirectory.Text.Length >  45 ? txtDirectory.Text :  "");
        }

         private  void tsslblViewDealList_Click( object sender, EventArgs e)
        {
            ShowFindResult();
        }

         private  void btnOpenDirectory_Click( object sender, EventArgs e)
        {
             if (Directory.Exists(txtDirectory.Text))
            {
                Process.Start(txtDirectory.Text);
            }
        }

         private  void btnSelectDirectory_Click( object sender, EventArgs e)
        {
             var fbd =  new FolderBrowserDialog();
             if (fbd.ShowDialog() == DialogResult.OK)
            {
                txtDirectory.Text = fbd.SelectedPath;
            }
        }
    }
}

 

處理結果窗體代碼

  

View Code
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;

namespace AFReplace
{
     public  partial  class FrmDealResult : Form
    {
         public FrmDealResult(List<KeyValue> filePtahs,  string formTitle)
        {
            InitializeComponent();
            Text = formTitle;
            Icon = Properties.Resources.window;
             if (filePtahs !=  null && filePtahs.Count >  0)
            {
                filePtahs.Sort((o1, o2) => String.Compare(o1.Value, o2.Value, StringComparison.Ordinal));

                lsbResults.DisplayMember =  " Value ";
                lsbResults.ValueMember =  " Key ";
                lsbResults.DataSource = filePtahs;
                tsslblMessage.Text =  " 共計記錄:  " + filePtahs.Count +  "  條 ";
            }
        }

         public  override  sealed  string Text
        {
             get {  return  base.Text; }
             set {  base.Text = value; }
        }

         private  void lsbResults_DoubleClick( object sender, EventArgs e)
        {
             if (lsbResults.SelectedItem !=  null)
            {
                 string filePath = ((KeyValue)lsbResults.SelectedItem).Key;
                 if (File.Exists(filePath))
                {
                    Process.Start(filePath);
                }
                 else
                {
                    tsslblMessage.Text =  " 文件不存在 ";
                }
            }
        }
    }
}

 

輔助類類名

 

View Code
namespace AFReplace
{
     public  class KeyValue
    {
         ///   <summary>
        
///  保存文件路徑
        
///   </summary>
         public  string Key {  getset; }
         ///   <summary>
        
///  顯示的文本
        
///   </summary>
         public  string Value {  getset; }
         public KeyValue( string key,  string value)
        {
            Key = key;
            Value = value;
        }
    }
}

 

下載

源碼下載

http://files.cnblogs.com/yelaiju/AFReplace_src.rar

 

可執行文件下載

http://files.cnblogs.com/yelaiju/AFReplacer.rar  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM