如何用C#正则更优雅地从nupkg文件名提取包名?
从NuGet包文件名中提取包名的优雅实现
我正在用C#和正则表达式从NuGet包文件名里提取包名,比如从az.accounts.2.10.4.nupkg中提取az.accounts。我已经有了可行的实现,但想知道有没有更优雅的写法。我的现有代码如下:
var filename = Path.GetFileNameWithoutExtension(nupkgPackagePath); var nupkgPackageGetModulePath = Regex.Matches(filename, @"[^\d]+").First().Value.TrimEnd('.');
测试用例
$ ls *.nupkg PowerShellGet.nupkg az.iothub.2.7.4.nupkg az.9.2.0.nupkg az.keyvault.4.9.1.nupkg az.accounts.2.10.4.nupkg az.kusto.2.1.0.nupkg az.advisor.2.0.0.nupkg az.logicapp.1.5.0.nupkg az.aks.5.1.0.nupkg az.machinelearning.1.1.3.nupkg az.analysisservices.1.1.4.nupkg az.maintenance.1.2.1.nupkg az.apimanagement.4.0.1.nupkg az.managedserviceidentity.1.1.0.nupkg az.appconfiguration.1.2.0.nupkg az.managedservices.3.0.0.nupkg az.applicationinsights.2.2.0.nupkg az.marketplaceordering.2.0.0.nupkg az.attestation.2.0.0.nupkg az.media.1.1.1.nupkg az.automation.1.8.0.nupkg az.migrate.2.1.0.nupkg az.batch.3.2.1.nupkg az.monitor.4.3.0.nupkg az.billing.2.0.0.nupkg az.mysql.1.1.0.nupkg az.cdn.2.1.0.nupkg az.network.5.2.0.nupkg az.cloudservice.1.1.0.nupkg az.notificationhubs.1.1.1.nupkg az.cognitiveservices.1.12.0.nupkg az.operationalinsights.3.2.0.nupkg az.compute.5.2.0.nupkg az.policyinsights.1.5.1.nupkg az.confidentialledger.1.0.0.nupkg az.postgresql.1.1.0.nupkg az.containerinstance.3.1.0.nupkg az.powerbiembedded.1.2.0.nupkg az.containerregistry.3.0.0.nupkg az.privatedns.1.0.3.nupkg az.cosmosdb.1.9.0.nupkg az.recoveryservices.6.1.2.nupkg az.databoxedge.1.1.0.nupkg az.rediscache.1.6.0.nupkg az.databricks.1.4.0.nupkg az.redisenterprisecache.1.1.0.nupkg az.datafactory.1.16.11.nupkg az.relay.1.0.3.nupkg az.datalakeanalytics.1.0.2.nupkg az.resourcemover.1.1.0.nupkg az.datalakestore.1.3.0.nupkg az.resources.6.5.0.nupkg az.dataprotection.1.0.1.nupkg az.security.1.3.0.nupkg az.datashare.1.0.1.nupkg az.securityinsights.3.0.0.nupkg az.deploymentmanager.1.1.0.nupkg az.servicebus.2.1.0.nupkg az.desktopvirtualization.3.1.1.nupkg az.servicefabric.3.1.0.nupkg az.devtestlabs.1.0.2.nupkg az.signalr.1.5.0.nupkg az.dns.1.1.2.nupkg az.sql.4.1.0.nupkg az.eventgrid.1.5.0.nupkg az.sqlvirtualmachine.1.1.0.nupkg az.eventhub.3.2.0.nupkg az.stackhci.1.4.0.nupkg az.frontdoor.1.9.0.nupkg az.storage.5.2.0.nupkg az.functions.4.0.6.nupkg az.storagesync.1.7.0.nupkg az.hdinsight.5.0.1.nupkg az.streamanalytics.2.0.0.nupkg az.healthcareapis.2.0.0.nupkg az.support.1.0.0.nupkg
更优雅的实现方案
1. 改进正则表达式,一步到位
现有代码需要匹配后再做Trim操作,可通过正则直接捕获目标内容,省去后续字符串处理:
var filename = Path.GetFileNameWithoutExtension(nupkgPackagePath); var match = Regex.Match(filename, @"^(.+?)(?=\.\d)"); var packageName = match.Success ? match.Groups[1].Value : filename;
正则逻辑:从字符串开头以非贪婪模式匹配任意字符,直到遇到.数字的位置停止。直接获取不带末尾点的包名,对于无版本号的文件名(如PowerShellGet),正则匹配失败时直接返回原文件名。
2. 字符串分割实现(无需正则)
若不想使用正则,可通过分割字符串实现,逻辑为找到第一个纯数字段,取其前面的部分拼接:
var filename = Path.GetFileNameWithoutExtension(nupkgPackagePath); var segments = filename.Split('.'); var versionStartIndex = segments.TakeWhile(s => !s.All(char.IsDigit)).Count(); var packageName = string.Join(".", segments.Take(versionStartIndex));
该方法可读性更强,无需理解正则语法,能覆盖所有测试用例:
- 对于
az.accounts.2.10.4,取前两个非数字段拼接为az.accounts - 对于
az.9.2.0,取第一个非数字段az - 对于
PowerShellGet,所有段均为非数字,直接返回原字符串
3. NuGet官方库解析(最可靠方案)
若项目已引用NuGet相关库(如NuGet.Packaging),可直接用官方解析逻辑,避免自行处理边缘场景:
using NuGet.Packaging; var packageId = PackageIdValidator.GetValidPackageId(Path.GetFileNameWithoutExtension(nupkgPackagePath));
官方库会自动识别文件名中的版本部分,返回符合规范的包ID,是最稳妥的实现方式。
内容的提问来源于stack exchange,提问作者Node.JS
相关产品推荐
相关产品推荐

