[英]selection of line based on the pattern using ruby 2.2
我有一個名為Regional.txt的文件,其數據如下:
shell.SetMyFile "Ranger"
shell.SetMyErrorFile "Discovery"
shell.SetMyFileEnabled 1
shell.SetMyLogFileEnabled 1
現在,我使用ruby讀取此文件,並嘗試以Ranger和Discovery的身份過濾“ shell.SetMyFile”和“ shell.SetMyErrorFile”中的文本:
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,而不是Ranger和發現 。 這是因為包含? 考慮“ shell.SetMyFileEnabled”和“ shell.SetMyLogFileEnabled”的方法 。 如何將其過濾為所需的結果?
快速修復如下:
# 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
以將其轉換為哈希,以便通過鍵輕松查找:
讓我們創建您的文件。
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 :: foreach和Enumerator#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"]
另外,如果您希望將"Ranger"
和"Discovery"
綁定到其對應的行,則可以替換為:
arr << [label, value]
對於
arr << value
在這種情況下,返回值為:
[["shell.SetMyFile", "Ranger"], ["shell.SetMyErrorFile", "Discovery"]]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.