在某些字符串上使用异常替换字符串
本文关键字:字符串 异常 替换 | 更新日期: 2023-09-27 18:14:22
我有这行代码,我用它来准备一些CSS文件:
TheMinifiedCSS = TheMinifiedCSS.Replace("white", "#FFF");
问题是,在CSS中,我有这样的声明:
.SomeClass{white-space:pre-wrap;}
我如何改变.Replace
语句用#FFF
代替white
,但留下white-space
单独?
谢谢。
注意,我知道我可以添加TheMinifiedCSS = TheMinifiedCSS.Replace("#FFF-space", "white-space");
,但我正在寻找更干净的东西。
人们一直试图为出现在"white"
之前或之后的东西编写规则,当我认为需要的是"white"
是它自己的令牌而不是选择器的一部分时。
Regex.Replace(TheMinifiedCSS, @"(?<![-_a-zA-Z0-9#.])white(?![-_a-zA-Z0-9])", @"#FFF");
一个更完整的规则将实现CSS中标识符令牌的整个规则,但我认为这个规则涵盖了所有关键字。
这是一个比目前为止发布的稍微棘手的测试用例:
.white> TD { color: white;box-shadow: 0px 0px 3px white, inset 0px 0px 5px black; white-space:pre-wrap; }
BODY { background: url('test.png'),white; }
更棘手的是文件名,我的例子没有处理。
BODY
{
background-color:white;
background-image:url('almost white, but not really.png');
}
要做到这一点,您可能需要一个完整的CSS解析器。
可以使用正则表达式。我认为这是对你最好的办法。这里是链接,你可以获得更多的详细信息:
http://msdn.microsoft.com/en-us/library/xwewhkd1.aspx我不是很擅长为正则表达式构建模式,但是你可以试试这个示例
static void Main(string[] args)
{
var inputText = @"white-space: 0; color: white;
box-shadow: 10px 20px 30px white, inset 0px 0px 5px black;";
inputText = ChangeColor(inputText, "white", "#FFF");
}
private static string ChangeColor(string css, string oldColor, string newColor)
{
// Rule 1
var pattern1 = string.Format(@"(color)('s*):('s*){0}('s*)", oldColor);
var replacement = string.Format("$1 : {0}", newColor);
var rgx = new Regex(pattern1);
css = rgx.Replace(css, replacement);
// Rule 2
var pattern2 = string.Format(@"(['d]*)px('s*)(['d]*)px('s*)(['d]*)px('s*){0}", oldColor);
var replacement2 = string.Format("$1px $3px $5px {0}", newColor);
rgx = new Regex(pattern2);
css = rgx.Replace(css, replacement2);
return css;
}
Regex可以使事情变得更加复杂。这里有一个有效的解决方案。也有注释和字符串的解决方案。
static void Main(string[] args)
{
string test = ".white> TD { color: white;box-shadow: 0px 0px 3px white, inset 0px 0px 5px black; white-space:pre-wrap; background-image='white black '" white '"'}";
Console.WriteLine("Before: " + test);
test = replaceInCSS(test, "white", "green");
Console.WriteLine("After: " + test);
Console.ReadLine();
}
static string replaceInCSS(string text, string replace, string replacement)
{
char[] forceBefore = new char[]{ ''n', ''t', ';', '{', ' ', ':', ','};
char[] forceAfter = new char[] { ';', '}', ' ', ','};
int index = text.IndexOf(replace, 0);
while (index != -1)
{
if (!indexWithinStringOrComment(text, index))
{
int afterPos = index + replace.Length;
bool beforeOk = false, afterOk = false;
if (index > 0 && forceBefore.Contains<char>(text[index - 1]))
beforeOk = true;
if (afterPos < text.Length - 1 && forceAfter.Contains<char>(text[afterPos]))
afterOk = true;
if ((index == 0 || beforeOk) &&
(afterPos == text.Length - 1 || afterOk))
{
text = text.Remove(index, replace.Length);
text = text.Insert(index, replacement);
}
}
index = text.IndexOf(replace, index + 1);
}
return text;
}
static bool indexWithinStringOrComment(string text, int index)
{
bool insideStrSimple = false;
bool insideStrDouble = false;
bool insideStrComment = false;
for (int i = 0; i < index; ++i)
{
string subStr = text.Substring(i, 2);
if (text[i] == '''' && !insideStrDouble && !insideStrComment)
insideStrSimple = !insideStrSimple;
else if (text[i] == '"' && !insideStrSimple && !insideStrComment)
insideStrDouble = !insideStrDouble;
else if (text.Substring(i, 2) == "/*" && !insideStrDouble && !insideStrSimple)
insideStrComment = true;
else if (text.Substring(i, 2) == "*/" && insideStrComment)
insideStrComment = false;
}
return insideStrDouble || insideStrSimple || insideStrComment;
}
输出:Before: .white> TD { color: white;box-shadow: 0px 0px 3px white, inset 0px 0px 5px black; white-space:pre-wrap; background-image='white black '" white '"'}
After: .white> TD { color: green;box-shadow: 0px 0px 3px green, inset 0px 0px 5px black; white-space:pre-wrap; background-image='white black '" white '"'}
编辑:好了。内部字符串问题也得到了解决。这应该可以用来替换任何css属性。再次编辑:添加注释的修复。
一个简单的破解方法是只在:
TheMinifiedCSS = TheMinifiedCSS.Replace(": white", ":#FFF");
这样它只会替换css-values而不是属性。
在我看来,最好的方法是要么使用正则表达式,要么使用CSS解析器并完全重建文档。
顺便说一句:如果你这样做是为了学习目的,这是可以的,但是如果你想把它用于生产目的,我强烈建议你使用一个已经完成所有这些的现有组件。
简单…
TheMinifedCSS = Regex.Replace(TheMinifiedCSS, @":(.*)white(.*);", @":$1#FFF$2;")
基本上检查它是否在冒号之后,然后取所有字符直到白色,替换然后获得所有字符之后,然后是分号。之后,它将css
放在替换white
(#FFF
)的新位周围,然后在其后面加上分号。
这将是查找字符串white
&替换为#FFF
TheMinifedCSS =
Regex.Replace(TheMinifiedCSS, @"(:(.*)(white)(.*);|:[ ]*(white)[ ]*})", @"#FFF");
它处理中间的空格,如:{color: white}
{color:white}
都是有效的。
您可以查看此链接以获取更多参考:http://regexr.com?34tqv