【正则表达式专家呼叫!!!!】关于python语法if else表达式去除前缩进空格的问题。

boyxia 2009-02-04 12:36:20
有如下表达式字符串:
string str1 = @"



if 条件1 :
if 子条件1 : 子结果1
else 子条件2 : 子结果2
elif 条件2 :
计算2
elif 条件3 : 计算3
elif 条件4 : 计算4

else :
计算5

";

要点:
1.表达式规则一般有一下几种形式:
第一种:
if <条件> : <结果> _回车
(这里可能带几个换行)
elif <条件> : <结果> _回车
else : <结果>
这种情况一般 <结果>是单个计算表达式,没有if else子逻辑运算表达式
第二种:
if <条件> : _回车
<结果> _回车
elif <条件> : _回车
<结果> _回车
else :
<结果>
这种 <结果>一般是单个计算表达式或含有if else的子逻辑运算表达式
第三种:
混用的情况,如例子的顶层的if和最后的else。
2. <结果>内可能嵌套其他if else表达式,不过if else前肯定有缩进空格
3.从前缩进空格数可以看出是否同组的if else。
4.存在只有if没有elif或else的情况。
5.if elif else肯定都是小写。

需求:
将头尾多余空格和回车去掉,而且第一层的if elif else开头的前面空格都去掉,子层嵌套的可以不随主层次的一同缩进,也可以不缩进。

预期结果:
string str1 = @"if 条件1 :
if 子条件1 : 子结果1
else 子条件2 : 子结果2
elif 条件2 :
计算2
elif 条件3 : 计算3
elif 条件4 : 计算4

else :
计算5";



string str1 = @"if 条件1 :
if 子条件1 : 子结果1
else 子条件2 : 子结果2
elif 条件2 :
计算2
elif 条件3 : 计算3
elif 条件4 : 计算4

else :
计算5;
...全文
2257 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
utopia54 2009-02-05
  • 打赏
  • 举报
回复
CSDN要是有正则表达式的版主就好了...
boyxia 2009-02-05
  • 打赏
  • 举报
回复
嗯,的确,测试了一下,6500个循环编译前用7s,编译后用5s,看来我只有自己写算法解析字符串了。
wuyi8808 2009-02-05
  • 打赏
  • 举报
回复
不过正则表达式的特点就是比较慢,可能预编译后速度改善不会很明显。
wuyi8808 2009-02-05
  • 打赏
  • 举报
回复
            pattern = @"(?msix)
^(\s*)if\b(?<key1>.*?):(?<value1>.*?) # 匹配 if 并记录前导空格
(^\1elif\b(?<key2>.*?):(?<value2>.*?))* # 匹配对应的 elif ,0个或多个
(^\1else\b(?<key3>.*?):(?<value3>.*?))? # 匹配对应的 else ,0个或1个
\Z # 匹配整个字符串末尾
";


? 和 <keyX>/<valueX> 之间多了一个空格。
boyxia 2009-02-05
  • 打赏
  • 举报
回复
System.ArgumentException: 正在分析“(?msix)
^(\s*)if\b(? <key1>.*?):(? <value1>.*?)
(^\1elif\b(? <key2>.*?):(? <value2>.*?))*
(^\1else\b(? <key3>.*?):(? <value3>.*?))?
\Z
”- 无法识别的分组构造。
boyxia 2009-02-05
  • 打赏
  • 举报
回复
我在构造里预编译,但是报错。


pattern = @"(?msix)
^(\s*)if\b(? <key1>.*?):(? <value1>.*?) # 匹配 if 并记录前导空格
(^\1elif\b(? <key2>.*?):(? <value2>.*?))* # 匹配对应的 elif ,0个或多个
(^\1else\b(? <key3>.*?):(? <value3>.*?))? # 匹配对应的 else ,0个或1个
\Z # 匹配整个字符串末尾
";
regex = new Regex(pattern, RegexOptions.Compiled);

代码:

static string pattern;
static Regex regex;

public void SetUp()
{
pattern = @"(?msix)
^(\s*)if\b(? <key1>.*?):(? <value1>.*?) # 匹配 if 并记录前导空格
(^\1elif\b(? <key2>.*?):(? <value2>.*?))* # 匹配对应的 elif ,0个或多个
(^\1else\b(? <key3>.*?):(? <value3>.*?))? # 匹配对应的 else ,0个或1个
\Z # 匹配整个字符串末尾
";
regex = new Regex(pattern, RegexOptions.Compiled);
}
wuyi8808 2009-02-05
  • 打赏
  • 举报
回复
// 可以考虑把正则表达式预编译为程序集,生成正则表达式的 Microsoft 中间语言 (MSIL) 代码;
// 以较长的启动时间为代价,得到更快的执行速度。

static string pattern = @"(?msix)
^(\s*)if\b(? <key1>.*?):(? <value1>.*?) # 匹配 if 并记录前导空格
(^\1elif\b(? <key2>.*?):(? <value2>.*?))* # 匹配对应的 elif ,0个或多个
(^\1else\b(? <key3>.*?):(? <value3>.*?))? # 匹配对应的 else ,0个或1个
\Z # 匹配整个字符串末尾
";
static Regex regex = new Regex(pattern, RegexOptions.Compiled);

private ArrayList GetLogicFormulaTopLevelIfThenList(string orginalFormulaScript)
{
ArrayList targetList = new ArrayList();

orginalFormulaScript = orginalFormulaScript.Trim().Replace("\r\n", "\n");
MatchCollection mc = regex.Matches(orginalFormulaScript);
foreach (Match m in mc)
{
// ...
}
}
boyxia 2009-02-05
  • 打赏
  • 举报
回复
这个问题解决了,不过之前你给我解答的一个正则问题有性能问题。帮忙分析一下。不行的话只能用字符串解析了。


[Test]
public void RegTestIfElse1()
{
string str1 = @"
if [当月考勤表.病假] > 0 :



if #连续工龄#<10 : #基薪标准#*0.5+(#基薪标准#*0.5*[当月考勤表.病假]/21.75) + #基薪标准#*([当月考勤表.事假]+[当月考勤表.旷工])/21.75
elif #连续工龄#<20 and #连续工龄#>=10 : #基薪标准#*0.4+(#基薪标准#*0.4*[当月考勤表.病假]/21.75) + #基薪标准#*([当月考勤表.事假]+[当月考勤表.旷工])/21.75
elif #连续工龄#<30 and #连续工龄#>=20 : #基薪标准#*0.3+(#基薪标准#*0.3*[当月考勤表.病假]/21.75) + #基薪标准#*([当月考勤表.事假]+[当月考勤表.旷工])/21.75
elif #连续工龄#>=30 : #基薪标准#*0.2+(#基薪标准#*0.2*[当月考勤表.病假]/21.75) + #基薪标准#*([当月考勤表.事假]+[当月考勤表.旷工])/21.75
else : 0
elif 1==1: #基薪标准#*([当月考勤表.事假]+[当月考勤表.旷工])/21.75
";
for (int i = 0; i < 6500 * 10; i++)
{
ArrayList targetTable = GetLogicFormulaTopLevelIfThenList(str1);

Assert.AreEqual(2, targetTable.Count);
}//这里要20多秒,循环次数接近但小于正式场景。
}

private ArrayList GetLogicFormulaTopLevelIfThenList(string orginalFormulaScript)
{
ArrayList targetList = new ArrayList();

orginalFormulaScript = orginalFormulaScript.Trim().Replace("\r\n", "\n");
string pattern = @"(?msix)
^(\s*)if\b(?<key1>.*?):(?<value1>.*?) # 匹配 if 并记录前导空格
(^\1elif\b(?<key2>.*?):(?<value2>.*?))* # 匹配对应的 elif ,0个或多个
(^\1else\b(?<key3>.*?):(?<value3>.*?))? # 匹配对应的 else ,0个或1个
\Z # 匹配整个字符串末尾
";
MatchCollection mc = Regex.Matches(orginalFormulaScript, pattern);
foreach (Match m in mc)
{
// 匹配到的第一个 if 的 key1 及 value1
KeyValuePair<string, string> kv1 = new KeyValuePair<string, string>(m.Groups["key1"].Value.Trim(), m.Groups["value1"].Value);
if (!kv1.Key.Equals(string.Empty) || !kv1.Value.Equals(string.Empty))
{
targetList.Add(kv1);
}

// 匹配到的 elif 的 key2 及 value2 (可能有多个捕获组)
int i = 0;
foreach (Capture c in m.Groups["key2"].Captures)
{
KeyValuePair<string, string> kv2 = new KeyValuePair<string, string>(c.Value.Trim(), m.Groups["value2"].Captures[i++].Value);
if (!kv2.Key.Equals(string.Empty) || !kv2.Value.Equals(string.Empty))
{
targetList.Add(kv2);
}
}

if (m.Groups["key3"].Success)
{
// 匹配到的 else 的 key3 及 value3
KeyValuePair<string, string> kv3 = new KeyValuePair<string, string>("1 == 1", m.Groups["value3"].Value);
if (!kv3.Key.Equals(string.Empty) || !kv3.Value.Equals(string.Empty))
{
targetList.Add(kv3);
}
}
}
return targetList;
}
boyxia 2009-02-05
  • 打赏
  • 举报
回复
你的回复我pm都收到了。

空军真是热心,感激犹如滔滔江水连绵不绝啊,无以回报,只能谢了。说来惭愧,开发很多年了,很早就知道正则表达式重要,不过一直都在做项目开发,没专下心来深入学习这块,惭愧。
lovelan1748 2009-02-05
  • 打赏
  • 举报
回复
...
wuyi8808 2009-02-04
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20090104/14/730129c8-0843-4918-8c3d-8d99f8508888.html

【求个小正则】密码至少要设8位数以上,其中至少要三个字母

我的解答是:

"(?i)^(?=.*[A-Z].*[A-Z].*[A-Z]).{8,}$"
wuyi8808 2009-02-04
  • 打赏
  • 举报
回复
另外在贴子:
http://topic.csdn.net/u/20090203/09/341714a1-2595-4564-a0af-0ced7b9bc8a5.html
的末尾我加了个回复:


[Quote=引用 3 楼 boyxia 的回复:]
还在测试中,目前比较理想,不过在没有else的时候,多匹配了一个键和值都为空的对,看看能否完善一小下。[/Quote]

在最后一小段前面加上是否实际捕获的判断 if (m.Groups["key3"].Success) 就可以了:

      // 匹配到的 else 的 key3 及 value3
if (m.Groups["key3"].Success)
{
string key3 = m.Groups["key3" ].Value.Trim();
string value3 = m.Groups["value3"].Value;
Console.WriteLine("Key3 = [{0}]", key3 );
Console.WriteLine("Value3 = [{0}]", value3);
}
wuyi8808 2009-02-04
  • 打赏
  • 举报
回复
using System;
using System.Text.RegularExpressions;

class Program
{
static string str1 = @"


if 条件1 :
if 子条件1 : 子结果1
else 子条件2 : 子结果2
elif 条件2 :
计算2
elif 条件3 : 计算3
elif 条件4 : 计算4

else :
计算5

";

static void Main()
{
string s = RemoveEmptyLine(str1);
s = RemoveStartSapces(s);
Console.WriteLine("[{0}]", s);
}

// 去除空行
static string RemoveEmptyLine(string s)
{
return Regex.Replace(s, @"(?m)^\s*$", "").Replace("\n\n", "\n").TrimStart('\r', '\n');
// 如果也想去掉末尾的回车,只需所把 TrimStart 改成 Trim 即可。
}

// 去除开头的空白
static string RemoveStartSapces(string s)
{
string spaces = Regex.Match(s, @"^\s*").Value;
return Regex.Replace(s, "(?m)^" + spaces, "");
}
}

/* 输出:
[if 条件1 :
if 子条件1 : 子结果1
else 子条件2 : 子结果2
elif 条件2 :
计算2
elif 条件3 : 计算3
elif 条件4 : 计算4
else :
计算5
]
*/
wuyi8808 2009-02-04
  • 打赏
  • 举报
回复
using System;
using System.Text.RegularExpressions;

class Program
{
static string str1 = @"


if 条件1 :
if 子条件1 : 子结果1
else 子条件2 : 子结果2
elif 条件2 :
计算2
elif 条件3 : 计算3
elif 条件4 : 计算4

else :
计算5

";

static void Main()
{
string s = RemoveEmptyLine(str1);
s = RemoveStartSapces(s);
Console.WriteLine("[{0}]", s);
}

// 去除空行
static string RemoveEmptyLine(string s)
{
return Regex.Replace(s, @"(?m)^\s*$", "").Replace("\r\n\r\n", "\r\n").TrimStart('\r', '\n');
// 如果也想去掉末尾的回车,只需所把 TrimStart 改成 Trim 即可。
}

// 去除开头的空白
static string RemoveStartSapces(string s)
{
string spaces = Regex.Match(s, @"^\s*").Value;
return Regex.Replace(s, "(?m)^" + spaces, "");
}
}
boyxia 2009-02-04
  • 打赏
  • 举报
回复
再顶一顶,快顶不住了~~~~~~~~~
boyxia 2009-02-04
  • 打赏
  • 举报
回复
顶一顶~~~~~
boyxia 2009-02-04
  • 打赏
  • 举报
回复
都不在么?先谢啦~~~~~

110,549

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧