2017-01-09 23 views
3

我有一个本地化的字符串,看起来在英语中是这样的:正则表达式来提取若干步骤


5英里(S)
5,252步骤(S)

我的应用程序是以左向右和从右向左语言进行本地化的,因此我不想对step(s)的排序或关于数字格式的假设(例如5,252可以是5.2 52取决于用户区域设置)。所以,我需要考虑的可能性,可以加入

步骤(S)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)
1482步骤(一个或多个)

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

+0

我想你也想提取里程。但要澄清,你*只*想要的步骤? – sweaver2112

+0

从右到左在这里是错误的术语。在RTL语言中,数据显示*的方式是数字在单词的右侧,但是**字符的顺序仍然是相同的**:'\ d + \ w +'对于希伯来语将起作用。语言环境仍然可能会优先选择单词后面的数字。一个例子是货币:[20美元对20美元](http://english.stackexchange.com/a/11341/220) – Kobi

回答

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)]; 

如果不亚太经社会e (s)那么正则表达式引擎可能会将其解释为捕获组。在NSLog

看你能看到什么模式实际上倒像是:

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

输出:

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

至于正则表达式,也许这种方法可能会奏效 - 它只是号码中的各个对联相匹配(与命名组)的序列中,假设第一是英里,第二个是步骤。在.,形式小数可选:

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

(我想应该是\\s) - 我不是一个IOS的家伙,但如果你可以使用正则表达式字面这将是方式更具有可读性。

regular expression demo

+0

感谢您的建议。我应该在上面详细说明我的答案,以表明我不想承担里面的“Miles”部分。 – helloB

+0

他的解决方案没有提到“英里数”。 '(? ...)'只是您可以参考的简单提取组的名称。它不匹配任何东西。 – sapanoia

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|...)
1

首先我想问 - 为什么Mile(s)在所有问题中提到?

而现在我的两位 - 你可以简单地使用正前瞻:

^(?=.*Step\(s\))[^\d]*(\d+(?:[.,]\d+)?) 

它确保预期的词存在就行了,然后捕获用户的数量,允许本地化,可选,小数分隔符和小数点。这样,数字在“单词”之前还是之后并不重要。

它不走“字”进去的国产化,但你似乎已经自行处理;)

See it here at regex101