$\sqrt {\left( {\sqrt[3]{5} - \sqrt[3]{4}} \right)} = \frac{1}{3}\left( {\sqrt[3]{2} + \sqrt[3]{20} - \sqrt[3]{{25}}}\right),$


$\sqrt { {\sqrt[3]{5} - \sqrt[3]{4}} } = \frac{1}{3}\left( {\sqrt[3]{2} + \sqrt[3]{20} - \sqrt[3]{{25}}}\right),$


$\sqrt[\mbox{\raisebox{0.8ex}{\mbox{{\mbox{{}^3}}}}}]{\left( {\sqrt[3]{2} - 1} \right)}= \sqrt[\mbox{\raisebox{1.5ex}{\mbox{{\mbox{{}^3}}}}}]{\left( {\frac{1}{9}} \right)}- \sqrt[\mbox{\raisebox{1.5ex}{\mbox{{\mbox{{}^3}}}}}]{\left( {\frac{2}{9}} \right)}+ \sqrt[\mbox{\raisebox{1.5ex}{\mbox{{\mbox{{}^3}}}}}]{\left( {\frac{4}{9}} \right)},$


$\sqrt[\mbox{\raisebox{0.8ex}{\mbox{{\mbox{{}^3}}}}}]{ {\sqrt[3]{2} - 1} }= \sqrt[\mbox{\raisebox{1.5ex}{\mbox{{\mbox{{}^3}}}}}]{ {\frac{1}{9}} }- \sqrt[\mbox{\raisebox{1.5ex}{\mbox{{\mbox{{}^3}}}}}]{ {\frac{2}{9}} }+ \sqrt[\mbox{\raisebox{1.5ex}{\mbox{{\mbox{{}^3}}}}}]{ {\frac{4}{9}} },$


$mcs sqrttransformer.cs && ./sqrttransformer.exe 5 3 ../ch00.tex 273 41 ../ch01.tex 109 50 ../ch02.tex 58 34 ../ch03.tex 52 10 ../ch04.tex 53 36 ../ch05.tex 216 156 ../ch06.tex 70 61 ../ch07.tex 101 62 ../ch08.tex 112 75 ../ch09.tex 59 46 ../ch10.tex 7 7 ../ch99.tex 1115 581 Total$


 1 using System;
2 using System.IO;
3
4 static class SqrtTransformer
5 {
6   static readonly string S = "\\sqrt", L = "\\left", R = "\\right";
7   static readonly string[] Ls = {"(","[","\\{",L+"(",L+"[",L+"\\{"};
8   static readonly string[] Rs = {")","]","\\}",R+")",R+"]",R+"\\}"};
9   static int n1 = 0, n2 = 0;
10
11   static string DeleteBracket(string s)
12   {
13     if (s.Length < 5 || s[0] != '{' || s[s.Length - 1] != '}') return s;
14     var i0 = 1; while (char.IsWhiteSpace(s, i0)) i0++;
15     for (var k = 0; k < Ls.Length; k++) {
16       if (!s.Substring(i0).StartsWith(Ls[k])) continue;
17       var i1 = s.IndexOf(Rs[k], i0 += Ls[k].Length);
19       var i2 = i1 + Rs[k].Length; while (char.IsWhiteSpace(s, i2)) i2++;
20       if (i2 + 1 != s.Length) return s; // right bracket isn't most right
21       return Transform("{" + s.Substring(i0, i1 - i0) + "}");
22     }
23     return s;
24   }
25
26   static (int Left, int Right) GetBoundary(string s, int i)
27   {
28     for (i += S.Length; char.IsWhiteSpace(s, i); ) i++;
29     if (s[i] == '[') { while (s[i] != ']') i++; i++; }
30     while (char.IsWhiteSpace(s, i)) i++; int i0;
31     if (s[i0 = i] != '{') return (i, i); //TODO: s[i] == '\\'
32     for (var n=1; n>0;) if (s[++i]=='{') n++; else if (s[i]=='}') n--;
33     return (i0, i); // s[i0] == '{' && s[i] == '}'
34   }
35
36   static string Transform(string s)
37   {
38     var t = new System.Text.StringBuilder();
39     for (int j, i = 0; i < s.Length; i++) {
40       if ((j = s.IndexOf(S, i)) < 0) { t.Append(s.Substring(i)); break; }
41       var (b, d) = GetBoundary(s, j);  t.Append(s.Substring(i, b - i));
42       string s2, s1 = s.Substring(b, (i = d) - b + 1);
43       t.Append(s2 = DeleteBracket(s1)); n1++; if (s1 != s2) n2++;
44     }
45     return t.ToString();
46   }
47
48   static void Main()
49   {
50     int i1 = 0, i2 = 0;
51     foreach (var file in Directory.GetFiles("..", "ch??.tex")) {
53       Console.WriteLine("{0,4} {1,3} {2}", n1 - i1, n2 - i2, file);
54       i1 = n1; i2 = n2;
55     }
56     Console.WriteLine("{0,4} {1,3} Total", n1, n2);
57   }
58 }


• 第 51 行的 foreach 循环遍历全书各章（ch00.tex, ch01.tex, ...）。
• 第 52 行的 File.ReadAllText 方法把某一章全部读入内存。
• 然后调用 Transform 方法进行转换（去掉不必要的括号）。
• 接着调用 File.WriteAllText 方法把这一章写回 ch??.tex 文件。
• 第 36 至 46 行的 Transform 方法执行转换。主要是查找 "\sqrt"，然后调用 GetBoundary 方法找出其后的以 '{' 和 '}' 表示的左右边界，再去掉其中的不必要的括号。
• 第 26 至 34 行的 GetBoundary 方法寻找 "\sqrt" 的左右边界。
• 第 29 行跳过 "[...]"（对应于开平方以外的情况）。
• 第 31 行对应被开方数是单个符号的情况。其中有可能是 \Delta 这样用多个字符表示的单个符号，但是对我们的目的没有影响，为简单起见，直接定界为 \ 就行了。
• 第 32 行定界 "{...}" 的情况，其中允许有嵌套的 "{}"。
• 第 11 至 24 行的 DeleteBracket 方法删除不必要的括号。
• 第 16 行判断根式中是不是以左括号开头。
• 第 17 行寻找匹配的右括号。
• 第 18 行处理找不到匹配的右括号的情况。
• 第 20 行处理右括号后面不是紧接着右边界的情况，此时这对括号是必要的，不能删除。
• 第 21 行递归调用 Transform 方法以删除嵌套的根式中的不必要的括号。

if (s[i0 = i] != '{') {
if (s[i] != '\\') return (i, i);
for (i0 = i++; char.IsLetter(s, i); ) i++;
return (i0, i - 1);
}