简体   繁体   English

用转义字符反转字符串

[英]Reversing a string with escape characters

I have a string that might contain escape characters. 我有一个可能包含转义字符的字符串。 Let's assume this is '\\'. 假设这是“ \\”。 I follow the MSDN Escape Sequences definition 我遵循MSDN转义序列的定义

I want to reverse this string, but keep the escape sequences. 我想反转此字符串,但保留转义序列。

Example: 例:

string input = @"Hello\_World";
string reversed = @"dlroW\_elloH";

Note that in my input string the backslashes are separate characters. 请注意,在我的输入字符串中,反斜杠是单独的字符。 The reversed string is meant to be used in a SQL LIKE statement where the underscore is not meant as a wild card, but literally as an underscore. 反向字符串应在SQL LIKE语句中使用,其中下划线不是通配符,而实际上是下划线。 The backslash in the SQL LIKE functions as an escape character SQL LIKE中的反斜杠用作转义符

The problem is, that if a character in my original string is preceded by a backslash, then in my reversed string this backslash should still precede the character: @"_" (two separate characters) should in reverse still be @"_". 问题是,如果原始字符串中的字符前面带有反斜杠,那么在我的反向字符串中,该反斜杠仍应位于字符之前:@“ _”(两个单独的字符)应反过来仍为@“ _”。

Bonus points: Reverse escape sequences with numbers '\\x0128' 加分点:反向转义序列,数字为'\\ x0128'

I've tried it as extension functions: 我已经尝试过将其作为扩展功能:

public static string EscapedReverse(this string txt, char escapeChar)
{
    IList<char> charList = txt.ToList();
    return new string(EscapedReverse(charList, escapeChar).ToArray());
}

public static IEnumerable<char> EscapedReverse(this IList<char> text, char escapeChar)
{
    int i = text.Count-1;
    // Text[i] is the last character of the sequence;
    // text[i] is the next character to return, except if text[i-1] is escapeChar
    while (i > 0)
    {
        if(text[i-1] == escapeChar)
        {
            yield return text[i-1];
            yield return text[i];
            i -= 2;
        }
        else
        {
            yield return text[i];
            i -= 1;
        }
    }
    // return the last character
    if (i == 0)
        yield return text[i];
}

This works. 这可行。 However, my string is converted to array / list twice. 但是,我的字符串两次转换为数组/列表。 I wondered if there would be a smarter method where the elements don't have to be accessed so often? 我想知道是否会有一种更聪明的方法来不必经常访问元素?

Addition: what is my problem anyway? 另外:我到底有什么问题?

Comments suggested to add more information about my problem. 建议添加有关我的问题的更多信息。

There is a requirement to show a list of matching elements while an operator is typing in a text box. 当操作员在文本框中键入内容时,需要显示匹配元素的列表。 Most elements he can see start with a similar prefix. 他可以看到的大多数元素都以相似的前缀开头。 The difference the operator searches for is in the end of the name. 操作员搜索的区别在于名称的末尾。

Therefore we want to show a list of names ending with the typed character. 因此,我们要显示以键入字符结尾的名称列表。 So if the operator types "World" he will see a list with all names ending with "World". 因此,如果操作员键入“世界”,他将看到一个列表,其中所有名称都以“世界”结尾。

The already existing database (change is out of the question) has a table with a NAME and a REVERSEDNAME. 已经存在的数据库(无法更改)具有一个带有NAME和REVERSEDNAME的表。 Software takes care that if a name is inserted or updated the correct reversed name is inserted / updated. 软件应注意,如果插入或更新了名称,则将插入/更新正确的反向名称。 REVERSEDNAME is indexed, so using a WHERE with reversed name is fast. REVERSEDNAME已建立索引,因此使用带有反向名称的WHERE很快。

So if I need to return all names ending with "World", I need to return the names of all records where the REVERSEDNAME starts with the reverse of "WORLD": 因此,如果我需要返回所有以“ World”结尾的名称,则需要返回REVERSEDNAME以“ WORLD”开头的所有记录的名称:

SELECT TOP 30 [MYTABLE].[NAME] as Name
FROM [MYTABLE]
WHERE [MYTABLE].REVERSEDNAME LIKE 'dlroW%'

This works fine as long as no wild cards (like underscore) are used. 只要不使用通配符(如下划线),此方法就可以正常工作。 This was solved by the software by escaping the underscore character (I know, bad design, the fact that SQL LIKE uses underscore as wild card should not seep through, but I have to live with this existing software) 这是由软件通过转义下划线字符来解决的(我知道,糟糕的设计,SQL LIKE使用下划线作为通配符这一事实不应渗入,但是我必须使用此现有软件)

So the operator types @"My_World" My software received @"My_World", the backslash is a separate character I have to reverse to @"dlrow_yM", note that the backslash is still before the underscore 因此,操作员键入@“ My_World”,我的软件收到@“ My_World”,反斜杠是我必须反转为@“ dlrow_yM”的独立字符,请注意,反斜杠仍在下划线之前

My Dapper code: 我的Dapper代码:

IEnumerable<string> FetchNamesEndingWith(string nameEnd)

// here is my reversal procedure:
string reversedNameEnd = nameEnd.EscapedReverse() = '%';

using (var dbConnection = this.CreateOpenDbConnection())
{
    return dbConnection.Query<string>(@"
        SELECT TOP 30 [MYTABLE].[NAME] as Name
        FROM [MYTABLE]
        WHERE [MYTABLE].REVERSEDNAME LIKE @param ESCAPE '\'",
        new {param = reversedNameEnd});
}

MSDN about using escape characters in SQL LIKE MSDN关于在SQL LIKE中使用转义字符

Changing the escape character to a different character doesn't help. 将转义字符更改为其他字符无济于事。 The problem is not that the escape character is a backslash, but that reversing my string should keep the escape character in front of the escaped character. 问题不在于转义字符是反斜杠,而是反转我的字符串应该使转义字符保持在转义字符的前面。

My code works, I only wondered if there would be a better algorithm that doesn't copy the string twice. 我的代码有效,我只想知道是否有更好的算法不会将字符串复制两次。 Not only for this specific problem, but also if in future problems I need to reverse strings and keep certain characters in place. 不仅针对此特定问题,而且如果将来出现问题,我都需要反转字符串并将某些字符保留在适当的位置。

You can use regular expressions: 您可以使用正则表达式:

var pattern =  @"\\x[1-9a-fA-F]{4}|\\x[1-9a-fA-F]{2}|\\[0-7]{3}|\\.|.";
var rgx = new Regex(pattern);
return new string(
          rgx.Matches(txt)
          .Cast<Match>()
          .OrderByDescending(x => x.Index)
          .SelectMany(x => x.Value)
          .ToArray());

pattern covers single characters and escape sequences in formats: 模式涵盖以下格式的单个字符和转义序列:

\x????
\x??
\???
\?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM