正则表达式以提取若干步骤

时间:2017-01-09 21:39:27

标签: objective-c regex

我有一个本地化的字符串,在英语中看起来像这样:

  

"
  5英里(s)   5,252步骤
  "

我的应用程序本地化为从左到右和从右到左的语言,因此我不想对step(s)的排序或数字的格式做出假设(例如,5,252可以是5.252,具体取决于用户的区域设置)。所以我需要考虑可能包括

等内容的可能性
  

步骤5.252

以及上面的内容。

其他一些警告

  • 我所知道的是,如果Step(s)行在那里,它将在它自己的行上(因此在我的正则表达式中我需要\ n在字符串的每一端)
  • 不保证Mile(s)信息根本不在字符串中,更不用说是Step(s)之前还是之后

这是我对模式提取的尝试:

NSString *patternString = [NSString stringWithFormat:@"\\n(([0-9,\\.]*)\s*%@|%@\s*([0-9,\\.]*))\\n",
    NSLocalizedString(@"Step(s)",nil), NSLocalizedString(@"Step(s)",nil)];

这似乎有两个问题:

  • XCode在上面的模式字符串中为第二个Unknown escape sequence '\s'指示\s
  • 即使对于以下字符串,也找不到匹配项:
  

0.2英里(s)   1,482步骤

理想情况下,我会以本地化友好的方式从该字符串中提取1,482。我应该如何修改我的正则表达式?

4 个答案:

答案 0 :(得分:1)

就正则表达式而言,也许这种方法可能有效 - 它只是按顺序匹配(与命名组)每个数字对应的数字,假设第一个是英里,第二个是步骤。 .,形式的小数是可选的:

(?<miles>\d+(?:[.,]\d+)?).*?(?<steps>\d+(?:[.,]\d+)?)

(我认为它应该是\\s) - 我不是ios家伙,但如果你可以使用正则表达式文字那么它会更具可读性。

regular expression demo

答案 1 :(得分:1)

首先我想问一下 - 为什么问题中提到了.as-console-wrapper { max-height: 100% !important; top: 0; }

现在我的两位 - 你可以简单地使用积极的预测:

Mile(s)

它确保该行上存在预期的单词,然后捕获其上的数字,允许本地化,可选,小数分隔符和小数。这样,如果数字是在#34;之前或之后,那么这并不重要。

它没有采取&#34;字的本地化&#34;考虑到,但你似乎已经自己处理了;)

See it here at regex101

答案 2 :(得分:0)

您的正则表达式已接近,但在Obj-C中您需要双重转义\s(s)

^(([0-9,.]*)\\s*%@|%@\\s*([0-9,.]*))$

在您的NSLocalizedString中,您可能还需要绕过括号(s)的括号:

 NSString *patternString = [NSString stringWithFormat:@"^(([\\d,.]+)\\s%@|%@\\s([\\d,.]+))$",
      NSLocalizedString(@"Step\\(s\\)",nil), NSLocalizedString(@"Step\\(s\\)",nil)];

如果你没有转义(s),那么正则表达式引擎可能会将其解释为捕获组。

查看 NSLog ,您可以看到模式的实际内容:

NSLog(@"patternString: %@", patternString);

<强>输出:

patternString: ^(([\d,.]+)\sStep\(s\)|Step\(s\)\s([\d,.]+))$

答案 3 :(得分:0)

由于您提到Mile(s)部分可能根本不在字符串中,我认为它与正则表达式无关。据我从这个问题中理解,你只需要捕获步骤数而不需要其他任何东西。在此基础上,这是您现有正则表达式的修改版本:

NSString *patternString = 
    [NSString stringWithFormat:@"^(?:([0-9,.]*)\\s*%@|%@\\s*([0-9,.]*))$",
    NSLocalizedString(@"Step\\(s\\)",nil), NSLocalizedString(@"Step\\(s\\)",nil)];

演示: https://www.regex101.com/r/Q6ff1b/1

这是基于以下提示/修改:

  1. 在创建正则表达式时使用m(= UREGEX_MULTILINE)标记选项,以指定^$匹配每行的开头和结尾。这比使用\n更复杂,因为它还将处理可能不存在的字符串的开头和结尾。见here
  2. 始终使用双反斜杠(\\)进行正则表达式转义 - 否则NSString将解释单个反斜杠以转义下一个字符并在它到达正则表达式之前进行转换。
  3. 字面括号需要转义 - 例如Step\\(s\\)代替Step(s)
  4. 角色类中的字符(即[]方括号内的任何内容)不需要进行转义 - 因此它将是.而不是\\. - 后者
  5. 如果您使用(x|y|...)作为选择并且不需要它作为捕获组,请在第一个括号后使用?:以确保它不会被捕获 - 即(?:x|y|...)