5

我有这行代码用来准备一些 CSS 文件:

TheMinifiedCSS = TheMinifiedCSS.Replace("white", "#FFF");

问题是在 CSS 中,我有这个声明:

.SomeClass{white-space:pre-wrap;}

如何更改.Replace语句以替换white#FFF不理会white-space

谢谢。

请注意,我知道我可以添加TheMinifiedCSS = TheMinifiedCSS.Replace("#FFF-space", "white-space");,但我正在寻找更清洁的东西。

4

6 回答 6

6

"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 解析器。

于 2013-05-19T17:31:58.373 回答
1

您可以使用正则表达式。我认为这对你来说是最好的方式。这是您可以获得更多详细信息的链接:

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;
}
于 2013-05-19T16:00:46.853 回答
1

正则表达式可以使事情变得更加复杂。这是一个有效的解决方案。也有评论和字符串的解决方案。

    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 属性。再次编辑:为评论添加了修复。

于 2013-05-19T18:06:50.383 回答
0

简单...应该适用于大多数目的:

TheMinifedCSS = Regex.Replace(TheMinifiedCSS, @":(.*)white(.*);", @":$1#FFF$2;")

基本上检查它是否在冒号之后,然后取所有字符直到白色,替换然后获取所有字符,然后是分号。之后,它将替换( )css的新位放在周围,然后是分号。white#FFF

于 2013-05-19T16:27:27.630 回答
0

一个简单的技巧是仅在它前面带有:

TheMinifiedCSS = TheMinifiedCSS.Replace(": white", ":#FFF");

这样它只会替换 css-values 而不是属性。

但在我看来,最好的方法是使用正则表达式或使用 CSS 解析器并完全重建文档。

顺便说一句:如果您这样做是出于学习目的,那没关系,但是如果您想将其用于生产目的,我强烈建议您使用已经完成所有这些操作的现有组件。

于 2013-05-19T16:02:25.937 回答
0

这将是查找字符串white并将其替换为的最有效方法#FFF

TheMinifedCSS = 
Regex.Replace(TheMinifiedCSS, @"(:(.*)(white)(.*);|:[ ]*(white)[ ]*})", @"#FFF");

它处理两者之间的空间:{color: white} {color:white}两者都是有效的。

您可以查看此链接以供进一步参考:http ://regexr.com?34tqv

于 2013-05-19T16:38:21.323 回答