1

我有一个名为region.txt的文件,它的数据如下:

shell.SetMyFile "Ranger" 
shell.SetMyErrorFile "Discovery"
shell.SetMyFileEnabled 1 
shell.SetMyLogFileEnabled 1

现在我正在使用 ruby​​ 读取此文件,并尝试将“shell.SetMyFile”“shell.SetMyErrorFile”中的文本过滤为RangerDiscovery

File.readlines("regional.txt").each do |line|
      value1 = line.split(" ")[1] if line.include?("shell.SetMyFile")
      value2 = line.split(" ")[1] if line.include?("shell.SetMyErrorFile ")
      puts value1, value2
end

我的结果是1 , 1而不是RangerDiscovery。这是因为包括?考虑到 "shell.SetMyFileEnabled""shell.SetMyLogFileEnabled"的方法。如何将其过滤到所需的结果?

4

2 回答 2

2

快速修复如下:

# Need to declare the variables outside the block,
# so they are not trapped in that scope
value1 = nil
value2 = nil

File.readlines("regional.txt").each do |line|
  # NOTE: added trailing space here:
  if line.include?("shell.SetMyFile ")
    value1 = line.split(" ")[1] 
  end
  if line.include?("shell.SetMyErrorFile ")
    value2 = line.split(" ")[1] 
  end
end

puts value1, value2
# => "Ranger"
# => "Discovery"

您也可以使用正则表达式来做到这一点:

key_vals = File.
  read("regional.txt").
  scan(/\w+\.(\w+)[^\w]+(\w+)/).
  to_h

value1 = key_vals["SetMyFile"]
# => "Ranger"

value2 = key_vals["SetMyErrorFile"]
# => "Discovery"

要解释正则表达式,请考虑shell.SetMyFile "Ranger"

  • \w+: 任意数量的字母数字字符,匹配前缀,例如shell
  • \.: 字面句号
  • (\w+): 匹配组 1,任意数量的字母数字字符,匹配后缀,例如SetMyFile
  • [^\w]+任意数量的非字母数字字符,匹配空格和引号
  • (\w+)匹配组 2,任意数量的字母数字字符。匹配值字符串,例如Ranger

调用后,scan您将得到一个嵌套数组:

File.read("regional.txt").scan(/\w+\.(\w+) \"?(\w+)/)
# => [
#   ["SetMyFile", "Ranger"],
#   ["SetMyErrorFile", "Discovery"], 
#   ["SetMyFileEnabled", "1"],
#   ["SetMyLogFileEnabled", "1"]
# ]

您可以调用to_h它来将其转换为哈希,以便通过键轻松查找:

于 2019-08-13T19:53:29.710 回答
0

让我们创建您的文件。

FName = "regional.txt"

File.write FName, <<~END
shell.SetMyFile "Ranger" 
shell.SetMyErrorFile "Discovery"
shell.SetMyFileEnabled 1 
shell.SetMyLogFileEnabled 1
END
  #=> 113

我们得到:

desired_lines = ["shell.SetMyFile", "shell.SetMyErrorFile"]

我了解到您希望打印文件中的某些信息。一般来说,最好将所需信息提取到 Ruby 对象中,然后打印感兴趣的信息。这样,如果您希望在代码中操作生成的对象,则不必更改代码的那部分。

可以将文件的行读入一个数组,选择感兴趣的元素,然后提取感兴趣的信息。但是,逐行读取文件并从以 的元素开头的那些行中保存感兴趣的信息会更有效,desired_lines这只需要一次通过文件并避免构建中间数组的需要。您可以使用IO::foreachEnumerator#with_object方法来做到这一点:

a = IO.foreach(FName).with_object([]) do |line,arr|
  label, value = line.chomp.delete('"').split
  arr << value if desired_lines.include?(label)
end
  #=> ["Ranger", "Discovery"] 

或者,如果您希望 tie"Ranger""Discovery"它们对应的行,您可以替换:

arr << [label, value]

为了

arr << value

在这种情况下,返回值将是:

[["shell.SetMyFile", "Ranger"], ["shell.SetMyErrorFile", "Discovery"]] 
于 2019-08-13T23:32:26.473 回答