【问题标题】:Ruby Regex match a newline followed by anything but (3 uppercase characters followed by a pipe)Ruby Regex 匹配换行符,后跟除(3 个大写字符后跟管道)以外的任何内容
【发布时间】:2016-02-23 18:43:08
【问题描述】:

(希望)这里有简单的正则表达式问题。我正在寻找匹配 1 个或多个换行符,这些换行符后面不是由三个大写字符和一个管道 (|) 组成的特定模式,并删除它们。

举个例子,我想转这个:

foo bar foo bar.



Normal

0

false

false

false



EN-US

JA


X-NONE




foo bar foo bar




|||||HH
OBX|156|TX|foo bar|||N
OBX|157|TX|foo bar

进入这个:

foo bar foo bar. Normal  0 false  false false  EN-US JA  X-NONE|||||HH
OBX|156|TX|foo bar|||N
OBX|157|TX|foo bar

我有一个在 Sublime 中非常有用的正则表达式:

(\n+)(?!MSH|PID|NTE|PV1|RXO|ORC|DG1|OBR|OBX).*

但在 ruby​​ 中,它并没有摆脱换行符。将崇高的正则表达式转换为 Rails 的正则表达式时,我有什么遗漏吗?

@r.force_encoding("UTF-8").gsub("\r\n","\r").gsub("(\r+)(?!MSH|PID|NTE|PV1|RXO|ORC|DG1|OBR|OBX)(.*)"," $2")

【问题讨论】:

  • 您是否尝试过将正则表达式表示为正则表达式而不是字符串?即:gsub(/(\r+).../) 而不是 gsub("(\r+)...")
  • 你可以像这样简化正则表达式:\n+(?!([A-Z]{3}).*).
  • 我不明白为什么你想要的输出的第一行不是foo bar foo bar.Normal0falsefalsefalseEN-USJAX-NONEfoo bar foo bar|||||HH。也就是说,为什么换行符组转换为空格(以及为什么有时有一个空格,有时有两个空格)以及第二个"foo bar foo bar" 发生了什么?
  • @Cary Swoveland,我在做这个例子时有点匆忙,基本上我只是想将一个或多个换行符的组转换为一个空格。 @archana 和 @tadman 使用 // 而不是字符串。
  • 您应该编辑以更正所需的输出,因为您的问题虽然得到了回答,但将来可能会被许多人阅读。

标签: ruby-on-rails ruby regex sublimetext


【解决方案1】:
str = <<-MULTI
foo bar foo bar.



Normal

0

false

false

false



EN-US

JA


X-NONE




foo bar foo bar




|||||HH
OBX|156|TX|foo bar|||N
OBX|157|TX|foo bar
MULTI

str.gsub(/(\n+)(?!MSH|PID|NTE|PV1|RXO|ORC|DG1|OBR|OBX).*/,'')

# It gives your desired result

【讨论】:

  • 这个答案对我有用,但你能解释一下为什么你的答案比我的更有效吗? / 的行为是否与引号不同?
  • 您的正则表达式是一种模式。引号内的任何内容都是字符串而不是模式。请在此处阅读:ruby-doc.org/core-2.1.4/String.html#method-i-gsub。从此文档中“该模式通常是正则表达式;如果作为字符串给出,则它包含的任何正则表达式元字符都将按字面意思解释,例如 '\\d' 将匹配后跟 'd' 的反斜杠,而不是数字。”
  • 如果str = "abc\nOSBxyz"r = /(\n+)(?!MSH|PID|NTE|PV1|RXO|ORC|DG1|OBR|OBX).*/str.gsub(r,'') #=&gt; "abc",但它应该返回"abcOSBxyz",因为"OSB" 后面没有管道。如果str = "abc\nOSB|xyz"str.gsub(r,'') #=&gt; "abc",但在这种情况下它应该返回str
【解决方案2】:

我的解决方案是单独处理行,多行正则表达式可能会让很多人感到困惑。

.each_line 或 .lines 都返回单独的行。

.grep 会将数组与正则表达式或基于字符串的模式进行匹配。

.join 将获取单独的行并从结果中返回一个多行字符串。

str.each_line
   .grep( /^[A-Z]{3,3}\|.+/ )
   .join( '' )

至于正则表达式,我们也将其分解,现在我们只是逐行处理:

^      - Starting at the beginning of the line.
[A-Z]  - Only match the range of chars from 'A' to 'Z' ( all cap chars ).
{3, 3} - Match only 3 chars, no more, no less.
\|     - Followed by a '|' char.
.+     - Followed by 1+ chars of anything.

【讨论】:

  • 有问题:"abc".each_line.grep( /^[A-Z]{3,3}\|.+/ ).join( '' ) #=&gt; ""。两件小事:{3,3}{3} 相同,join('')join 相同。
  • 我更喜欢直言不讳。
【解决方案3】:

如果str 是你的字符串,

r = /
    \n+                        # match one or more newlines
    (?!                        # start a negative lookahead
      #{Regexp.union(keepers)} # match one of keepers
      \|                       # match pipe--escape required
    )                          # close negative lookahead 
    /x                         # extended/free-spacing regex definition mode
  #=> /
      \n+
      (?!
        (?-mix:MSH|PID|NTE|PV1|RXO|ORC|DG1|OBR|OBX)
        \|
      )
      /x 

keepers = %w[ MSH PID NTE PV1 RXO ORC DG1 OBR OBX ]
  #=> ["MSH", "PID", "NTE", "PV1", "RXO", "ORC", "DG1", "OBR", "OBX"] 

puts str.gsub(r, "")
  # foo bar foo bar.Normal0falsefalsefalseEN-USJAX-NONEfoo bar foo bar|||||HH
  # OBX|156|TX|foo bar|||N
  # OBX|157|TX|foo bar

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多