【问题标题】:C# how to find and replace specific text in string?C#如何查找和替换字符串中的特定文本?
【发布时间】:2019-02-28 20:39:54
【问题描述】:

我有一个代表字节数组string,在其中我有几组数字(通常是5):编码为@987654323 @(0..9 数字的代码)。 之前之后每个数字我都有一个空格0x20代码)。

示例:

"E5-20-32-36-20-E0"                // "32-36" encodes number "26", notice spaces: "20"
"E5-20-37-20-E9"                   // "37" encodes number "7"
"E5-20-38-20-E7-E4-20-37-35-20-E9" // two numbers: "8" (from "38") and "75" (from "37-35")

我想找出所有这些组和编码数字中的反转数字

   8 -> 8
  75 -> 57
 123 -> 321

期望的结果:

"E5-20-32-36-20-E0"                   -> "E5-20-36-32-20-E0"
"E5-20-37-20-E9"                      -> "E5-20-37-20-E9"
"E5-20-37-38-39-20-E9"                -> "E5-20-39-38-37-20-E9" 
"E5-20-38-39-20-E7-E4-20-37-35-20-E9" -> "E5-20-39-38-20-E7-E4-20-35-37-20-E9"

我在List\String\Byte[] 中有数据 - 所以也许有办法做到这一点?

谢谢,

【问题讨论】:

  • 看看方法string.Replace
  • 但我不知道我在找什么.....我现在不知道这个数字是 26 还是 37....
  • 我写的......我需要找到消息里面的数字并替换顺序
  • 您想如何更换订单?只是颠倒它们还是以其他方式?
  • @julianbechtold 根据其他 cmets 的说法,他们想颠倒顺序,但前提是它是一个数字。我认为?

标签: c# arrays string replace find


【解决方案1】:

我不确定,但我猜长度可能会发生变化,您只想以相反的顺序重新排列数字。所以一种可能的方法是:

  • 将字符串放入 2 个数组中(所以它们是相同的)
  • 遍历其中一个以定位数字区域的开始和结束
  • 在第一个数组中从 end-area 到 begin-area,然后从 begin-area 到 end-area 写入第二个数组

编辑:没有真正测试过,我只是写得很快:

    string input = "E5-20-36-32-37-20-E0";
    string[] array1 = input.Split('-');
    string[] array2 = input.Split('-');

    int startIndex = -1;
    int endIndex = -1;

    for (int i= 0; i < array1.Length; ++i)
    {
        if (array1[i] == "20")
        {
            if (startIndex < 0)
            {
                startIndex = i + 1;
            }
            else
            {
                endIndex = i - 1;
            }
        }
    }

    int pos1 = startIndex;
    int pos2 = endIndex;
    for (int j=0; j < (endIndex- startIndex + 1); ++j)
    {
        array1[pos1] = array2[pos2];
        pos1++;
        pos2--;
    }

【讨论】:

  • 这是我想要的,也是我想做的——但是怎么做呢?
  • @David12123 请稍等一下,我会输入一些内容,但描述非常不言自明,您应该尝试 ^^
  • 我一直在尝试 - 这就是我在这里问的原因:-)
  • 我编辑了答案,可能不是最优雅的方法,但现在改进代码是你的工作,你有这个想法^^
  • 我的回答只考虑一个数字区域,但它的大小并不重要。我根本没有检查,玩数组索引时要小心,走得太远很容易,你应该添加一些保护
【解决方案2】:

如果您清楚要如何处理这些数字,则提供解决方案会更容易。

  • 要随机交换吗?
  • 您要颠倒顺序吗?
  • 是否要将每隔一个数字与之前的数字交换一次?
  • 你想换...

您可以尝试以下方法(用于反转数字)

string hex = "E5-20-36-32-20-E0"; // this is your input string

// split the numbers by '-' and generate list out of it
List<string> hexNumbers = new List<string>();
hexNumbers.AddRange(hex.Split('-'));

// find start and end of the numbers that should be swapped
int startIndex = hexNumbers.IndexOf("20");
int endIndex = hexNumbers.LastIndexOf("20");

string newHex = "";
// add the part in front of the numbers that should be reversed
for (int i = 0; i <= startIndex; i++) newHex += hexNumbers[i] + "-";
// reverse the numbers
for (int i = endIndex-1; i > startIndex; i--) newHex += hexNumbers[i] + "-";
// add the part behind the numbers that should be reversed
for (int i = endIndex; i < hexNumbers.Count-1; i++) newHex += hexNumbers[i] + "-";
newHex += hexNumbers.Last();

如果开始和结束始终相同,这可以相当简化为 4 行代码:

string[] hexNumbers = hex.Split('-');
string newHex = "E5-20-";
for (int i = hexNumbers.Count() - 3; i > 1; i--) newHex += hexNumbers[i] + "-";
newHex += "20-E0";

结果:

"E5-20-36-32-20-E0" -> "E5-20-32-36-20-E0"
"E5-20-36-32-37-20-E0"    -> "E5-20-32-37-36-20-E0"
"E5-20-36-12-18-32-20-E0" -> "E5-20-32-18-12-36-20-E0"

【讨论】:

  • 第一次使用 Regex,所以请解释一下(如果可以的话) - 我也收到此错误:严重代码描述项目文件行抑制状态错误 CS0019 运算符'&&'不能应用于类型的操作数'Match' 和 'bool' ReadSerailData
  • 我想交换顺序,而不是随机的——所以当我找到 0x39,0x34 时——我想将其更改为:0x34,0x39。如果我有 0x36,0x37,0x31 - 它将是 0x31,0x37,0x36
  • 抱歉@david 我的代码完全未经测试 - 现在该代码应该可以按照您的要求工作。 Regex(正则表达式)是一种匹配字符串的特殊格式。例如 [0-9] 匹配 0-9 之间的任何数字。 [0-9]+ 匹配从 0 到无限的任何数字。绝对值得一看
【解决方案3】:

不清楚(从原始问题)你想对数字做什么;让我们提取一个 自定义方法 供您实现。例如,我实现了 reverse

32          -> 32
32-36       -> 36-32
36-32-37    -> 37-32-36
36-37-38-39 -> 39-38-37-36

代码:

// items: array of digits codes, e.g. {"36", "32", "37"}
//TODO: put desired transformation here
private static IEnumerable<string> Transform(string[] items) {
  // Either terse Linq:
  // return items.Reverse();

  // Or good old for loop:
  string[] result = new string[items.Length];

  for (int i = 0; i < items.Length; ++i)
    result[i] = items[items.Length - i - 1];

  return result;
}

现在我们可以使用正则表达式 (Regex) 来提取所有数字序列并用转换后的序列替换它们:

  using System.Text.RegularExpressions;

  ...

  string input = "E5-20-36-32-37-20-E0";

  string result = Regex
    .Replace(input, 
           @"(?<=20\-)3[0-9](\-3[0-9])*(?=\-20)", 
             match => string.Join("-", Transform(match.Value.Split('-'))));

  Console.Write($"Before: {input}{Environment.NewLine}After:  {result}";);

结果:

Before: E5-20-36-32-37-20-E0
After:  E5-20-37-32-36-20-E0

编辑:如果 reverse 是唯一需要的转换,则可以通过删除 Transform 并添加 Linq 来简化代码:

using System.Linq;
using System.Text.RegularExpressions;

...

string input = "E5-20-36-32-37-20-E0";

string result = Regex
  .Replace(input, 
          @"(?<=20\-)3[0-9](\-3[0-9])*(?=\-20)", 
           match => string.Join("-", match.Value.Split('-').Reverse()));

更多测试:

private static string MySolution(string input) {
  return Regex
    .Replace(input,
           @"(?<=20\-)3[0-9](\-3[0-9])*(?=\-20)",
             match => string.Join("-", Transform(match.Value.Split('-'))));
} 

...

string[] tests = new string[] {
  "E5-20-32-36-20-E0",
  "E5-20-37-20-E9",
  "E5-20-37-38-39-20-E9",
  "E5-20-38-39-20-E7-E4-20-37-35-20-E9",
};

string report = string.Join(Environment.NewLine, tests
  .Select(test => $"{test,-37} -> {MySolution(test)}"));

Console.Write(report);

结果:

E5-20-32-36-20-E0                     -> E5-20-36-32-20-E0
E5-20-37-20-E9                        -> E5-20-37-20-E9
E5-20-37-38-39-20-E9                  -> E5-20-39-38-37-20-E9
E5-20-38-39-20-E7-E4-20-37-35-20-E9   -> E5-20-39-38-20-E7-E4-20-35-37-20-E9

编辑 2: 正则表达式解释(详见https://www.regular-expressions.info/lookaround.html):

   (?<=20\-)         - must appear before the match: "20-" ("-" escaped with "\")
   3[0-9](\-3[0-9])* - match itself (what we are replacing in Regex.Replace) 
   (?=\-20)          - must appear after the match "-20" ("-" escaped with "\")

我们来看看比赛部分3[0-9](\-3[0-9])*

   3           - just "3"
   [0-9]       - character (digit) within 0-9 range
   (\-3[0-9])* - followed by zero or more - "*" - groups of "-3[0-9]"

【讨论】:

  • 相当不错,但似乎他想要对数字索引进行完全反转。无论如何,我正在研究您刚刚放入的正则表达式^^。 @David12123:当需要测试正则表达式时,我喜欢分享这个(它可能对你有帮助):regex101.com
  • 对不起 - 但我似乎无法理解我没有解释清楚的内容 - 我想在我的字符串数组(十六进制)中找到数字并颠倒它的顺序: 12-21,123-321,1234-4321,55-55,1719-9171
  • @Mikitori:现在(在问题的唯一示例中,两个数字交换)我们只能猜测实际的转换应该是什么。这就是我提取Transform 方法的原因
  • @David12123:好的,我明白了;让我们编辑Transform 方法
  • @David12123:不客气!下一次,请多花几分钟时间提出问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
  • 2022-01-11
  • 1970-01-01
相关资源
最近更新 更多