1. 项目背景与核心功能设计
正则表达式作为文本处理的瑞士军刀,在Web开发和移动应用领域有着不可替代的作用。但它的语法晦涩难懂,调试过程往往令人抓狂。这个基于Flutter和OpenHarmony的正则表达式工具App,正是为了解决这一痛点而生。
我在实际开发中经常遇到这样的场景:写了一个复杂的正则表达式,却不确定它是否能匹配目标文本,或者想知道它会匹配哪些部分。传统的做法是反复修改代码、运行测试,效率极低。这个工具App的核心价值就在于提供实时可视化的正则表达式测试环境。
核心功能模块包括:
- 实时匹配引擎:输入正则和文本后立即显示匹配结果
- 可视化高亮:用颜色标记匹配成功的文本片段
- 替换操作:支持正则替换并显示结果
- 常用模板库:内置10个高频使用的正则表达式
- 语法速查:内置正则表达式语法参考手册
2. Flutter与OpenHarmony环境搭建
2.1 Flutter开发环境配置
开发这个工具App需要先配置Flutter开发环境。我推荐使用Flutter 3.41.9稳定版,对应的Dart SDK版本是3.1.5。安装步骤如下:
# 下载Flutter SDK wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.41.9-stable.tar.xz # 解压到目标目录 tar xf flutter_linux_3.41.9-stable.tar.xz -C ~/development # 添加环境变量 echo 'export PATH="$PATH:$HOME/development/flutter/bin"' >> ~/.bashrc source ~/.bashrc # 运行doctor检查环境 flutter doctor注意:如果遇到"you are applying flutter's main gradle plugin imperatively using the apply s"警告,可以忽略不影响使用。这是Flutter Gradle插件的一个已知问题。
2.2 OpenHarmony适配准备
为了让Flutter应用能在OpenHarmony上运行,需要配置鸿蒙版的Flutter SDK。macOS用户可以通过以下命令切换:
flutter channel openharmony flutter upgrade关键依赖项包括:
- hispark wifi iot套件(用于OpenHarmony设备连接)
- hi3861开发板驱动(如果使用润和智能小车开发套件)
- OpenHarmony的hvigor构建工具
3. 正则表达式核心功能实现
3.1 实时匹配引擎设计
匹配功能的核心是Dart的RegExp类。我们在StatefulWidget中维护两个TextEditingController分别处理正则表达式和测试文本的输入:
class _RegexTesterPageState extends State<RegexTesterPage> { final TextEditingController _regexController = TextEditingController(); final TextEditingController _textController = TextEditingController(); List<RegExpMatch> _matches = []; void _testRegex() { try { final regex = RegExp( _regexController.text, caseSensitive: _caseSensitive, multiLine: _multiLine, dotAll: _dotAll, ); _matches = regex.allMatches(_textController.text).toList(); } catch (e) { setState(() => _errorMessage = '正则表达式语法错误'); } } }实时匹配的关键是在文本变化时立即触发_testRegex()。我们通过监听Controller的onChanged事件实现:
TextField( controller: _regexController, onChanged: (_) => _testRegex(), )3.2 高亮显示实现技巧
匹配结果的高亮显示使用RichText和TextSpan组合实现。核心思路是将文本分为匹配和未匹配部分分别处理:
Widget _buildHighlightedText() { final text = _textController.text; final spans = <TextSpan>[]; int lastEnd = 0; for (var match in _matches) { // 未匹配部分 spans.add(TextSpan( text: text.substring(lastEnd, match.start), style: TextStyle(fontFamily: 'monospace'), )); // 匹配部分 spans.add(TextSpan( text: text.substring(match.start, match.end), style: TextStyle( backgroundColor: Colors.yellow[300], fontWeight: FontWeight.bold, ), )); lastEnd = match.end; } // 剩余文本 spans.add(TextSpan( text: text.substring(lastEnd), style: TextStyle(fontFamily: 'monospace'), )); return RichText(text: TextSpan(children: spans)); }3.3 正则选项的实用价值
三个核心选项对正则行为影响巨大:
- 区分大小写(caseSensitive):默认true。设为false时,[A-Z]也会匹配小写字母
- 多行模式(multiLine):改变^和$的行为,使其匹配每行的开始/结束而非整个字符串
- 点匹配所有(dotAll):让.元字符也能匹配换行符
这些选项通过Checkbox组件控制,状态变化时立即重新匹配:
Widget _buildCheckbox(String label, bool value, Function(bool) onChanged) { return Row( children: [ Checkbox( value: value, onChanged: (v) { onChanged(v ?? false); _testRegex(); // 选项变化时立即重新匹配 }, ), Text(label), ], ); }4. 进阶功能实现与优化
4.1 替换功能的完整实现
替换功能基于String的replaceAll方法,但增加了正则选项的支持:
String _getReplaceResult() { try { final regex = RegExp( _regexController.text, caseSensitive: _caseSensitive, multiLine: _multiLine, dotAll: _dotAll, ); return _textController.text.replaceAll(regex, _replaceController.text); } catch (e) { return '替换错误: ${e.toString()}'; } }UI层面提供替换文本输入框和执行按钮,结果显示在可滚动的区域内:
TextField( controller: _replaceController, decoration: InputDecoration(labelText: '替换为'), ), ElevatedButton( onPressed: () { final result = _getReplaceResult(); Clipboard.setData(ClipboardData(text: result)); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('替换结果已复制到剪贴板')), ); }, child: Text('执行替换'), ), SingleChildScrollView( child: SelectableText(_getReplaceResult()), )4.2 常用模板库的设计
模板数据使用List
final templates = [ { 'name': '手机号', 'regex': r'^1[3-9]\d{9}$', 'desc': '匹配中国大陆手机号' }, { 'name': '邮箱', 'regex': r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$', 'desc': '匹配电子邮箱地址' }, // 其他模板... ];模板列表使用ListView.builder渲染,点击时自动填充到正则输入框:
ListView.builder( itemCount: templates.length, itemBuilder: (context, index) { return Card( child: ListTile( title: Text(templates[index]['name']), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(templates[index]['desc']), Text( templates[index]['regex'], style: TextStyle(fontFamily: 'monospace'), ), ], ), onTap: () { _regexController.text = templates[index]['regex']; setState(() => _selectedTab = 0); // 切换到匹配标签 _testRegex(); }, ), ); }, )4.3 语法帮助的交互实现
语法帮助以对话框形式呈现,使用AlertDialog组件:
void _showHelp() { showDialog( context: context, builder: (context) => AlertDialog( title: Text('正则表达式语法'), content: SingleChildScrollView( child: Column( children: [ _buildHelpItem('.', '匹配任意单个字符'), _buildHelpItem(r'\d', '匹配数字'), _buildHelpItem(r'\w', '匹配字母数字下划线'), // 其他语法项... ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('关闭'), ), ], ), ); } Widget _buildHelpItem(String syntax, String desc) { return Padding( padding: EdgeInsets.symmetric(vertical: 8), child: Row( children: [ Container( width: 80, padding: EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(4), ), child: Text( syntax, style: TextStyle(fontFamily: 'monospace'), ), ), SizedBox(width: 16), Expanded(child: Text(desc)), ], ), ); }5. 性能优化与调试技巧
5.1 防抖处理优化性能
实时匹配虽然用户体验好,但频繁执行正则匹配可能导致性能问题。我们添加简单的防抖逻辑:
Timer? _debounceTimer; void _testRegex() { _debounceTimer?.cancel(); _debounceTimer = Timer(Duration(milliseconds: 300), () { // 实际匹配逻辑... }); }5.2 错误处理与用户反馈
正则表达式可能包含语法错误,需要进行妥善处理:
void _testRegex() { setState(() { _matches = []; _errorMessage = ''; try { final regex = RegExp(_regexController.text); _matches = regex.allMatches(_textController.text).toList(); } catch (e) { _errorMessage = '正则表达式错误: ${e.toString().split(':').last.trim()}'; } }); }在UI中显示错误信息:
if (_errorMessage.isNotEmpty) Text( _errorMessage, style: TextStyle(color: Colors.red), )5.3 测试文本编辑优化
长文本编辑时,提供全屏编辑对话框:
GestureDetector( onTap: () => _showFullScreenEditor(context), child: _buildHighlightedText(), ) void _showFullScreenEditor(BuildContext context) { showDialog( context: context, builder: (context) => AlertDialog( title: Text('编辑测试文本'), content: TextField( controller: _textController, maxLines: 20, autofocus: true, ), actions: [ TextButton( onPressed: () { Navigator.pop(context); _testRegex(); }, child: Text('确定'), ), ], ), ); }6. OpenHarmony适配经验分享
6.1 解决hvigor构建错误
在OpenHarmony上构建时可能遇到hvigor错误:
flutter hvigor error: failed :entry:default@compilearkts...解决方案是确保项目目录没有中文路径,并检查openharmony相关依赖是否完整:
flutter clean flutter pub get flutter run -d openharmony6.2 鸿蒙版Flutter特性适配
鸿蒙版的Flutter在UI渲染上有些差异需要注意:
- 部分Widget的渲染效果可能不同
- 动画性能需要特别优化
- 平台通道的调用方式有差异
建议在鸿蒙真机上频繁测试,早期发现问题。
6.3 多端部署策略
利用Flutter的跨平台特性,可以一套代码同时部署到OpenHarmony和其他平台:
# pubspec.yaml flutter: uses-material-design: true assets: - assets/regex_templates.json关键是要抽象平台相关代码,使用条件导入:
import 'package:flutter/foundation.dart' show kIsWeb; void _copyToClipboard(String text) { if (kIsWeb) { // Web端复制逻辑 } else { // 移动端复制逻辑 Clipboard.setData(ClipboardData(text: text)); } }7. 项目扩展与进阶方向
7.1 历史记录功能
使用shared_preferences保存用户常用的正则表达式:
final prefs = await SharedPreferences.getInstance(); await prefs.setStringList('regex_history', [..._history, _regexController.text]);7.2 性能测试模块
添加正则表达式执行时间统计:
void _testRegex() { final stopwatch = Stopwatch()..start(); // ...匹配逻辑 setState(() { _executionTime = stopwatch.elapsedMilliseconds; }); }7.3 可视化正则构建器
考虑添加图形化的正则表达式构建界面,降低学习曲线。可以借鉴regexr.com的交互方式,通过拖拽组件生成正则表达式。
7.4 测试用例管理
允许用户保存测试文本和预期结果,形成测试用例集,便于回归测试:
class RegexTestCase { final String name; final String pattern; final String testString; final List<String> expectedMatches; // 保存到本地数据库 Future<void> save() async { final db = await DatabaseHelper.instance.database; await db.insert('test_cases', toMap()); } }8. 项目打包与发布
8.1 Flutter打包注意事项
打包OpenHarmony应用时需要确保包含必要的原生库:
flutter build apk --target-platform android-arm64如果遇到VC++库缺失问题,可以在windows上打包时添加:
flutter build windows --release8.2 应用商店发布
发布到AppStore和各大应用市场的注意事项:
- 准备不同尺寸的应用截图
- 编写详细的应用描述
- 处理应用签名和证书
- 适配不同的屏幕密度
8.3 持续集成方案
配置GitHub Actions实现自动化构建和测试:
name: Flutter CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: subosito/flutter-action@v1 - run: flutter pub get - run: flutter test - run: flutter build apk --release9. 实际开发中的经验教训
在开发这个正则表达式工具的过程中,我积累了几个关键经验:
实时反馈至关重要:最初版本需要手动点击测试按钮,用户反馈很差。改为实时匹配后体验大幅提升。这告诉我,工具类应用必须尽可能减少用户操作步骤。
错误处理要友好:早期版本遇到错误的正则表达式时会直接崩溃。后来添加了try-catch和友好的错误提示,用户满意度明显提高。
模板库的价值超预期:原本以为模板只是锦上添花的功能,但实际上80%的用户都是从模板开始使用的。这提醒我要更重视开箱即用的体验。
性能优化需要平衡:实时匹配虽然体验好,但对复杂正则和长文本会有性能问题。最终采用防抖策略取得了不错的平衡。
跨平台差异不容忽视:在OpenHarmony上测试时发现了一些渲染差异,这提醒我跨平台开发不能只在一个平台上测试。