我是Ruby的新手。 在此脚本中,我想在第10行中使用选择器,而不是使用fields [0]等。 我该怎么办?
例如,数据是嵌入的。 如果我在打开或写入文件或其他任何我喜欢学习的过程中做错了,请毫不犹豫地纠正我。
#!/usr/bin/ruby
filename = "/tmp/log.csv"
selector = [0, 3, 5, 7]
out = File.open(filename + ".rb.txt", "w")
DATA.each_line do |line|
fields = line.split("|")
columns = fields[0], fields[3], fields[5], fields[7]
puts columns.join("|")
out.puts(columns.join("|"))
end
out.close
__END__
20180704150930|rtsp|645645643|30193|211|KLM|KLM00SD624817.ts|172.30.16.34|127299264|VERB|01780000|21103|277|server01|OK
20180704150931|api|456456546|30130|234|VC3|VC300179201139.ts|172.30.16.138|192271838|VERB|05540000|23404|414|server01|OK
20180704150931|api|465456786|30154|443|BAD|BAD004416550.ts|172.30.16.50|280212202|VERB|04740000|44301|18|server01|OK
20180704150931|api|5437863735|30157|383|VSS|VSS0011062009.ts|172.30.16.66|312727922|VERB|05700000|38303|381|server01|OK
20180704150931|api|3453432|30215|223|VAE|VAE00TF548197.ts|172.30.16.74|114127126|VERB|05060000|22305|35|server01|OK
20180704150931|api|312121|30044|487|BOV|BOVVAE00549424.ts|172.30.16.58|69139448|VERB|05300000|48708|131|server01|OK
20180704150931|rtsp|453432123|30127|203|GZD|GZD0900032066.ts|172.30.16.58|83164150|VERB|05460000|20303|793|server01|OK
20180704150932|api|12345348|30154|465|TYH|TYH0011224259.ts|172.30.16.50|279556843|VERB|04900000|46503|241|server01|OK
20180704150932|api|4343212312|30154|326|VAE|VAE00TF548637.ts|172.30.16.3|28966797|VERB|04740000|32601|969|server01|OK
20180704150932|api|312175665|64530|305|TTT|TTT000000011852.ts|172.30.16.98|47868183|VERB|04740000|30501|275|server01|OK
答案 0 :(得分:4)
您可以使用Ruby's splat operator(搜索“ splat”)和Array.values_at来获得特定索引处的fields
,如下所示:
columns = fields.values_at(*selector)
一些编码风格建议:
1。您可能希望将selector
设为常量,因为不太可能希望在代码库中对其进行进一步的突变
2。out
和out.close
并附加到DATA
都可以压缩成CSV.open:
CSV.open(filenname, 'wb') do |csv|
columns.map do |col|
csv << col
end
end
您还可以将自定义分隔符(在您的情况下为管道|
)设置为noted in this answer,如下所示:
...
CSV.open(filenname, 'wb', {col_sep: '|') do |csv|
...
答案 1 :(得分:2)
让我们从一个更易于管理的示例开始。首先请注意,如果字符串由变量n
保留,则字符串的每一行都包含相同数量(14)的竖线(#define CHECK_BIT(value, position) ((value) & (1 << position))
)。让我们将其减少到data
的前4行,每行紧接在第6个竖线之前终止:
'|'
我们还需要(任意)修改data
:
str = data.each_line.map { |line| line.split("|").first(6).join("|") }.first(4).join("\n")
puts str
20180704150930|rtsp|645645643|30193|211|KLM
20180704150931|api|456456546|30130|234|VC3
20180704150931|api|465456786|30154|443|BAD
20180704150931|api|5437863735|30157|383|VSS
现在要回答问题。
不需要将字符串分成几行,在垂直条上分割每一行,从结果数组中选择感兴趣的元素,将其与垂直条连接起来,然后最后用换行符( whew!)。相反,只需使用String#gsub从字符串中删除所有不需要的字符即可。
selector
最后,我们将selector = [0, 3, 4]
写入文件:
terms_per_row = str.each_line.first.count('|') + 1
#=> 6
r = /
(?:^|\|) # match the beginning of a line or a vertical bar in a non-capture group
[^|\n|]+ # match one or more characters other than a vertical bar or newline
/x # free-spacing regex definition mode
line_idx = -1
new_str = str.gsub(r) do |s|
line_idx += 1
selector.include?(line_idx % terms_per_row) ? s : ''
end
puts new_str
20180704150930|30193|211
20180704150931|30130|234
20180704150931|30154|443
20180704150931|30157|383