如果你需要在大量的代码文件中修改某个地方,那么最高效的办法就是使用正则进行批量处理。
下面介绍一个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;
}
}
}
}
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 = "文件不存在";
}
}
}
}
}
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 { get; set; }
/// <summary>
/// 显示的文本
/// </summary>
public string Value { get; set; }
public KeyValue(string key, string value)
{
Key = key;
Value = value;
}
}
}
{
public class KeyValue
{
/// <summary>
/// 保存文件路径
/// </summary>
public string Key { get; set; }
/// <summary>
/// 显示的文本
/// </summary>
public string Value { get; set; }
public KeyValue(string key, string value)
{
Key = key;
Value = value;
}
}
}
下载
源码下载:
https://files.cnblogs.com/yelaiju/AFReplace_src.rar
https://files.cnblogs.com/yelaiju/AFReplacer.rar
作者:
火地晋
出处: http://yelaiju.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处: http://yelaiju.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。