.NET Framework为我们提供了Format方法:
string s = string.Format("This {0} very {1}.", "is", "funny");
// s is now: "This is very funny."
我想要一个“Unformat”功能,例如:
object[] params = string.Unformat("This {0} very {1}.", "This is very funny.");
// params is now: ["is", "funny"]
我知道ANSI-C库中存在类似的东西(printf vs scanf)。
问题:C#中有类似内容吗?
更新:使用正则表达式捕获组不是我需要的解决方案。他们也是一种方式。我正在寻找一种能够以单一格式双向的系统。放弃一些功能(如类型和格式信息)是可以的。
答案 0 :(得分:15)
没有这样的方法,可能是因为解决含糊不清的问题:
string.Unformat("This {0} very {1}.", "This is very very funny.")
// are the parameters equal to "is" and "very funny", or "is very" and "funny"?
答案 1 :(得分:5)
如果有人感兴趣,我刚刚发布了scanf()
替代.NET。如果正则表达式没有为您完全删除它,我的代码非常接近scanf()
格式字符串。
您可以查看并下载我在http://www.blackbeltcoder.com/Articles/strings/a-sscanf-replacement-for-net撰写的代码。
答案 2 :(得分:4)
您可以执行string [] parts = string.Split(''),然后通过示例中的索引位置部分[1]和部分[3]进行提取。
答案 3 :(得分:4)
正则表达分组?
/This (.*?) very (.*?)./
答案 4 :(得分:3)
是的。这些被称为“正则表达式”。将要做的事情是
This (?<M0>.+) very (?<M1>.+)\.
答案 5 :(得分:1)
@mquander:Actualy,PHP解决它甚至不同:
$s = "This is very very funny.";
$fmt = "This %s very %s.";
sscanf($s, $fmt, $one, $two);
echo "<div>one: [$one], two: [$two]</div>\n";
//echo's: "one: [is], two: [very]"
但也许你的正则表达评论可以帮助我。我只需要将"This {0} very {1}."
重写为:new Regex(@"^This (.*) very (.*)\.$")
。这应该是程序化的,所以我可以在公共类接口上使用一个格式字符串。
BTW:我已经有了一个解析器来查找参数:请参阅Named Format Redux的Phil Haack博客条目(是的,我也希望命名参数可以双向工作)。
答案 6 :(得分:1)
我遇到了同样的问题,我相信有一个使用REGEX的优雅解决方案...但是在C#中提出了一个功能非常好的“UnFormat”功能。抱歉没有评论。
/// <summary>
/// Unformats a string using the original formating string.
///
/// Tested Situations:
/// UnFormat("<nobr alt=\"1\">1<nobr>", "<nobr alt=\"{0}\">{0}<nobr>") : "1"
/// UnFormat("<b>2</b>", "<b>{0}</b>") : "2"
/// UnFormat("3<br/>", "{0}<br/>") : "3"
/// UnFormat("<br/>4", "<br/>{0}") : "4"
/// UnFormat("5", "") : "5"
/// UnFormat("<nobr>6<nobr>", "<nobr>{0}<nobr>") : "6"
/// UnFormat("<nobr>2009-10-02<nobr>", "<nobr>{0:yyyy-MM-dd}<nobr>") : "2009-10-02"
/// UnFormat("<nobr><nobr>", "<nobr>{0}<nobr>") : ""
/// UnFormat("bla", "<nobr>{0}<nobr>") : "bla"
/// </summary>
/// <param name="original"></param>
/// <param name="formatString"></param>
/// <returns>If an "unformat" is not possible the original string is returned.</returns>
private Dictionary<int,string> UnFormat(string original, string formatString)
{
Dictionary<int, string> returnList = new Dictionary<int, string>();
try{
int index = -1;
// Decomposes Format String
List<string> formatDecomposed = new List<string> (formatString.Split('{'));
for(int i = formatDecomposed.Count - 1; i >= 0; i--)
{
index = formatDecomposed[i].IndexOf('}') + 1;
if (index > 0 && (formatDecomposed[i].Length - index) > 0)
{
formatDecomposed.Insert(i + 1, formatDecomposed[i].Substring(index, formatDecomposed[i].Length - index));
formatDecomposed[i] = formatDecomposed[i].Substring(0, index);
}
else
//Finished
break;
}
// Finds and indexes format parameters
index = 0;
for (int i = 0; i < formatDecomposed.Count; i++)
{
if (formatDecomposed[i].IndexOf('}') < 0)
{
index += formatDecomposed[i].Length;
}
else
{
// Parameter Index
int parameterIndex;
if (formatDecomposed[i].IndexOf(':')< 0)
parameterIndex = Convert.ToInt16(formatDecomposed[i].Substring(0, formatDecomposed[i].IndexOf('}')));
else
parameterIndex = Convert.ToInt16(formatDecomposed[i].Substring(0, formatDecomposed[i].IndexOf(':')));
// Parameter Value
if (returnList.ContainsKey(parameterIndex) == false)
{
string parameterValue;
if (formatDecomposed.Count > i + 1)
if (original.Length > index)
parameterValue = original.Substring(index, original.IndexOf(formatDecomposed[i + 1], index) - index);
else
// Original String not valid
break;
else
parameterValue = original.Substring(index, original.Length - index);
returnList.Add(parameterIndex, parameterValue);
index += parameterValue.Length;
}
else
index += returnList[parameterIndex].Length;
}
}
// Fail Safe #1
if (returnList.Count == 0) returnList.Add(0, original);
}
catch
{
// Fail Safe #2
returnList = new Dictionary<int, string>();
returnList.Add(0, original);
}
return returnList;
}
答案 7 :(得分:-1)
我参考前面的回复,写了一个样本见下面的
string sampleinput = "FirstWord.22222";
Match match = Regex.Match(sampleinput, @"(\w+)\.(\d+)$", RegexOptions.IgnoreCase);
if(match.Success){
string totalmatchstring = match.Groups[0]; // FirstWord.22222
string firstpart = match.Groups[1]; // FirstWord`
string secondpart = match.Groups[2]; // 22222
}