1 回答
TA贡献1827条经验 获得超9个赞
可以通过检查所有环境变量并检查字符串中包含哪个变量的值,然后将字符串的该部分替换为%.
第一次天真的尝试:
string Tokenify(string path)
{
foreach (DictionaryEntry e in Environment.GetEnvironmentVariables())
{
int index = path.IndexOf(e.Value.ToString());
if (index > -1)
{
//we need to make sure we're not already inside a tokenized part.
int numDelimiters = path.Take(index).Count(c => c == '%');
if (numDelimiters % 2 == 0)
{
path = path.Replace(e.Value.ToString(), $"%{e.Key.ToString()}%");
}
}
}
return path;
}
该代码当前错误地假设环境变量的值在路径中仅出现一次。这需要纠正,但我们暂时把它放在一边。
另请注意,并非所有环境变量都代表目录。例如,如果我在字符串 上运行此方法"6",我会得到"%PROCESSOR_LEVEL%"。Directory.Exists()这可以通过在使用环境变量值之前检查它来解决。这也可能使得检查我们是否已经处于字符串的标记化部分中的需要变得无效。
您可能还想按长度对环境变量进行排序,以便始终使用最具体的变量。否则你可能会得到:
%HOMEDRIVE%%HOMEPATH%\AppData\Local\Folder
代替:
%LOCALAPPDATA%\Folder
更新了更喜欢最长变量的代码:
string Tokenify(string path)
{
//first find all the environment variables that represent paths.
var validEnvVars = new List<KeyValuePair<string, string>>();
foreach (DictionaryEntry e in Environment.GetEnvironmentVariables())
{
string envPath = e.Value.ToString();
if (System.IO.Directory.Exists(envPath))
{
//this would be the place to add any other filters.
validEnvVars.Add(new KeyValuePair<string, string>(e.Key.ToString(), envPath));
}
}
//sort them by length so we always get the most specific one.
//if you are dealing with a large number of strings then orderedVars can be generated just once and cached.
var orderedVars = validEnvVars.OrderByDescending(kv => kv.Value.Length);
foreach (var kv in orderedVars)
{
//using regex just for case insensitivity. Otherwise just use string.Replace.
path = Regex.Replace(path, Regex.Escape(kv.Value), $"%{kv.Key}%", RegexOptions.IgnoreCase);
}
return path;
}
您可能仍然希望添加检查以避免对字符串的部分进行双重标记,但这在此版本中不太可能成为问题。
此外,您可能想过滤掉一些变量,例如驱动器根,例如 ( %HOMEDRIVE%) 或通过任何其他条件。
- 1 回答
- 0 关注
- 140 浏览
添加回答
举报