【问题标题】:Multiline file grep多行文件 grep
【发布时间】:2017-10-24 23:58:27
【问题描述】:

我有一个包含这样部分的文件,

flags...id, description, used, color
AB, "Abandoned", 0, 13168840
DM, "Demolished", 0, 15780518
OP, "Operational", 0, 15780518...

其中... 表示一系列控制字符,例如ETX 和 STX。我正在尝试从文件中获取多行。

我正在使用以下代码:

f = File.open(somePath)
r = f.grep(/flags.+id, description, used, color(?<data>(?:.|\s)*?)[\x00-\x08]/)

此代码不起作用。我不明白为什么。 grep 的文档似乎暗示该文件是逐行解析的。我有一种感觉,这可能是正则表达式没有返回任何结果的原因。

  1. 我是否纠正了 grep 使用逐行解析?这就是我的正则表达式没有按预期工作的原因吗?
  2. 使用file.each_line 捕获数据会更好吗?
  3. 是否有比上述所有更好/更清洁的替代方案?

【问题讨论】:

  • 你没有逃过.期间。你必须写\.
  • @sawa,你确定吗? Sancam 说“其中……代表一系列控制字符”。我认为他不会寻找经期。
  • @Philicare 我明白了。你是对的。

标签: ruby grep multiline


【解决方案1】:

String#scan 来救援:

File.read('/path/to/file').scan(
  /flags.+id, description, used, color(?<data>(?:.|\s)*?)[\x00-\x08]/m
)

【讨论】:

  • 看来问题实际上是我正在读取二进制文件。我可以使用File.binread("C:\\Users\\jwa\\Desktop\\TBD\\master.db") 来确保我得到整个文件,但正则表达式似乎仍然不起作用......但奇怪的是,即使扫描/./ 也不会返回任何结果......所以这很令人困惑...... xD 编辑: 糟糕,我的错误/./ 确实返回了匹配项。
  • 介意分享文件内容吗?我相信明确的File.binread().force_encoding(Encoding::BINARY) 会有所帮助。
  • 当然ufile.io/rsakp。我也尝试使用enforce_encoding,但它似乎不是我的旧版本 ruby​​ (1.9.1) 的方法。
  • Ruby 1.9.1?我洗手了,对不起。顺便说一句,方法名称是force_encoding,而不是enforce_encoding
  • 仅供参考,您的解决方案就像一个魅力。我的正则表达式也有一些问题。
【解决方案2】:

您需要启用多行模式。 . 默认不匹配换行符。

来自文档https://ruby-doc.org/core-2.1.1/Regexp.html

/./ - Any character except a newline.
/./m - Any character (the m modifier enables multiline mode)

【讨论】:

  • 但 \s 默认匹配新行。我认为这无关紧要。据我所知,m 意味着每一行都被视为自己的干草堆,因此 ^ 是行的开头,$ 是行的结尾。
【解决方案3】:

grep 使用逐行解析是否正确?

是的。试试你的文件:

r = File.open(somePath) do |f|
  f.grep(/[A-Z]{2},/)
end

puts r
# => AB, "Abandoned", 0, 13168840
#    DM, "Demolished", 0, 15780518
#    OP, "Operational", 0, 15780518

puts r.inspect
# => ["AB, \"Abandoned\", 0, 13168840\n", "DM, \"Demolished\", 0, 15780518\n", "OP, \"Operational\", 0, 15780518\n"]

这就是我的正则表达式没有按预期工作的原因吗?

不仅如此。你在用 [\x00-\x08] 搜索什么? ascii 还是十六进制字符?

使用 file.each_line 来捕获数据会更好吗?

File#grep 听起来不错。

【讨论】:

  • 我的意思是该文件确实包含的不仅仅是数据结构。文件本身是 8000kb,但它很酷。我将尝试使用逐行方法。我正在扫描的还有[\x00-\x08] 是文本部分末尾的控制字符。它不仅仅是一个 CSV 文件。它是(未记录的)专有数据库格式的整个数据库文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
  • 2014-09-19
  • 2019-07-31
相关资源
最近更新 更多