【问题标题】:Split CSV File, Name Based on Contents, Save As HTML拆分 CSV 文件,根据内容命名,另存为 HTML
【发布时间】:2021-07-02 14:10:41
【问题描述】:

Click here to view table

我认为这是一个简单的任务,但我是一个只懂一点代码的生物学家,经过几天的尝试,我无能为力:'(

在 Mac 上使用终端。我有一个 CSV 文件,我想按行(162 行)将其拆分为单独的文件,并且我想通过第一列和第二列(genus_species)的内容来命名文件。然后我需要将所有 162 个 genus_species 保存为 HTML 文件。

我只尝试了 Ruby 的“拆分”部分(来自 StackExchange/overflow 的推荐)。以下是我的一些尝试。他们是乐于助人的论坛的科学怪人,每次我都对它为什么不起作用发表一点评论。

示例 HTML

<!DOCTYPE html>
<html><head>
<meta charset="UTF-8">
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script></head>
<body>
<h1><em><!-- Species name --></em> - <!-- Common name --></h1>
<h2>Status</h2>
<p></p>
<h2>Info</h2>
<p></p>
<h2>Time of year this bee is seen</h2>
<p></p>
<h2>Identification</h2>
<p></p>
<h3>Similar Species</h3>
<p></p>
<h2>Flowers</h2>
<p></p>
<h2>Sociality</h2>
<p></p>
<h2>Nest</h2>
<p></p>
<div id="refs" class="references">

--<br>More information:<br> <!-- <a href="https://bugguide.net/node/view/70932">Bug Guide</a> --></div>
</body></html>

更多信息基于评论

以下是从文本文件中复制的一些行:

Genus,species,Common name,Status,Info,Time of year this bee is seen,Identification,Similar Species,Flowers,Sociality,Nest,Bug Guide,Discover Life,Other,
Agapostemon,melliventris,Honey-tailed Striped-Sweat bee,Secure G5,Excavates into deep burrows in ground nests,March-December,Agapostemon males have black and yellow stripes on the abdomen. Females have a yellow band on the lower margin of the clypeus.,All other Agapostemon species,Wide variety of plants,Solitary,"Deep, underground excavation",https://bugguide.net/node/view/70932,https://www.discoverlife.org/20/q?search=Agapostemon+melliventris,https://explorer.natureserve.org/Taxon/ELEMENT_GLOBAL.2.928401/Agapostemon_melliventris,
Agapostemon,sericeus,Silky Striped Sweat Bee,Secure G5,"Not choosy about lawn, as long as flowers are present",April-October,Agapostemon males have black and yellow stripes on the abdomen. A. sericeus males have a tooth on its hind femur. Female has metallic green abdomen.,All other Agapostemon species,Wide variety of plants,Solitary,Ground-nester in loamy soils,https://bugguide.net/node/view/83023,https://www.discoverlife.org/mp/20q?search=Agapostemon+sericeus,https://www.sharpeatmanguides.com/sweat-bees,
Agapostemon,splendens,Brown-winged Striped-Sweat Bee,Secure G5,This is the most common Agapostemon found in the southeast region,April-October,Agapostemon males have black and yellow stripes on the abdomen. A. splendens have brown wings. The female abdomen is often somewhat bluish.,All other Agapostemon species,"Jacquemontia reclinata, wide variety of plants",Solitary,Ground-nester in sandy soils,https://bugguide.net/node/view/74478,https://www.discoverlife.org/mp/20q?search=Agapostemon+splendens,,

更新了我基于 cmets 尝试过的代码。 这行得通,我认为它正朝着我想要的方向前进,但在终端窗口中很难说:

f = File.new("bee_key_fact_sheet .csv")
f.each_line { |line| puts line }
      Currently playing with some kind of File.write line to add here and then close? 

尝试 #1

file = File.open("bee_key_fact_sheet.csv")
    awk   
        '(NR==1){header=$0;next}
         (NR%l==2) {
         close(file); 
         file=sprintf("%s.%0.5d.csv",FILENAME,++c)
         sub(/csv[.]/,"",file)
         print header > file
            }
            {f.write}' 
                File.close

#AWK 无法识别,要求“显示所有可能性 (y/n)” 我尝试返回“y”和“yes”,但两次都说我的答案无法识别

尝试 #2

file_data = File.read("bee_key_fact_sheet.csv").split 

#这可行,但每个逗号分开

尝试 #3

file_data = File.foreach("bee_key_fact_sheet.csv") { |line| puts line}.split  

#这返回的东西比用每个逗号分割稍微少一些,但得到这个错误消息“undefined method `split' for nil:NilClass”

尝试 #4

bee_key_fact_sheet.csv.foreach('so1.csv', :headers => true, :col_sep => ",", :skip_blanks => true) do |row|
  id, name = row[0], row[1]
  unless (id =~ /#/)
    names = name.split
  end

#这没有返回任何内容

非常感谢您花时间阅读本文。

【问题讨论】:

  • 为什么这个问题用bash标记?
  • 请添加几行您的 CSV 文件以及您的“拆分”文件名和内容应该是什么
  • 对于@Fravadona 的评论,如果您要显示示例 CSV 文件的全部内容(包括标题行,如果有的话),读者会发现它非常有帮助,示例如下可能(根据字段和行的数量),同时保留文件的结构。然后提供要创建的文件的示例。
  • 大家好!我添加了表格的屏幕截图。 @cyrus 抱歉,我补充说,因为到目前为止对我有帮助的一些论坛已将其标记为(掌心)。
  • CSV 是一个文本文件。使用基本的文本编辑器(如 Windows 上的 Notepad.exe)打开它,并将其前 3 行放在此处。另外,你想用它创建 HTML 文件,你有例子吗?

标签: excel ruby csv split


【解决方案1】:

您的 CSV 输入示例 (bee_key_fact_sheet.csv):

Genus,species,Common name,Status,Info,Time of year this bee is seen,Identification,Similar Species,Flowers,Sociality,Nest,Bug Guide,Discover Life,Other,
Agapostemon,melliventris,Honey-tailed Striped-Sweat bee,Secure G5,Excavates into deep burrows in ground nests,March-December,Agapostemon males have black and yellow stripes on the abdomen. Females have a yellow band on the lower margin of the clypeus.,All other Agapostemon species,Wide variety of plants,Solitary,"Deep, underground excavation",https://bugguide.net/node/view/70932,https://www.discoverlife.org/20/q?search=Agapostemon+melliventris,https://explorer.natureserve.org/Taxon/ELEMENT_GLOBAL.2.928401/Agapostemon_melliventris,
Agapostemon,sericeus,Silky Striped Sweat Bee,Secure G5,"Not choosy about lawn, as long as flowers are present",April-October,Agapostemon males have black and yellow stripes on the abdomen. A. sericeus males have a tooth on its hind femur. Female has metallic green abdomen.,All other Agapostemon species,Wide variety of plants,Solitary,Ground-nester in loamy soils,https://bugguide.net/node/view/83023,https://www.discoverlife.org/mp/20q?search=Agapostemon+sericeus,https://www.sharpeatmanguides.com/sweat-bees,
Agapostemon,splendens,Brown-winged Striped-Sweat Bee,Secure G5,This is the most common Agapostemon found in the southeast region,April-October,Agapostemon males have black and yellow stripes on the abdomen. A. splendens have brown wings. The female abdomen is often somewhat bluish.,All other Agapostemon species,"Jacquemontia reclinata, wide variety of plants",Solitary,Ground-nester in sandy soils,https://bugguide.net/node/view/74478,https://www.discoverlife.org/mp/20q?search=Agapostemon+splendens,,

在此 CSV 中,所有行(包括标题)都以逗号结尾,因此最后一列可能没有任何意义,将被丢弃。
此外,数据中有逗号(带有双引号的字段),因此您需要一个 real CSV 解析器 来读取文件的内容。 顺便说一句,您选择 Ruby 来完成这项任务是正确的,因为它在其核心库中包含一个 CSV 解析器。

这是读取 CSV 的一种方式(编辑:修复了旧 Ruby 的 CSV#Row 转换):

require 'csv'
    
filepath = 'bee_key_fact_sheet.csv'
    
CSV.foreach(filepath, headers: true) do |row|
  genus, species = row[0], row[1]
  #data = row[0...-1] # NOTE: not sure about the Ruby version compatibility
  data = row.to_hash.values[0...-1]
    
  filename = "#{genus}_#{species}.txt".tr("\0/",'')
  filecontent = "  * #{data.join("\n  * ")}"
    
  puts "\n#{filename}:\n#{filecontent}"
end

关于tr("\0/",''):文件名中允许的字符取决于文件系统。所有的文件系统(据我所知)至少禁止 NULL-byteslash 字符,所以我去掉它们(但你可能想去掉更多) .

问题:预期的 HTML 输出究竟是什么?表格行?


更新:HTML 生成

以编程方式生成内容时,转义您的数据以获取正确的格式/语言/上下文至关重要。在 Ruby 中,您可以使用 CGI.escapeHTML

转义 HTML

您的 HTML 输出示例:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
  </head>
  <body>
    <h1><em><!-- Species name --></em> - <!-- Common name --></h1>
    <h2>Status</h2>
    <p></p>
    <h2>Info</h2>
    <p></p>
    <h2>Time of year this bee is seen</h2>
    <p></p>
    <h2>Identification</h2>
    <p></p>
    <h3>Similar Species</h3>
    <p></p>
    <h2>Flowers</h2>
    <p></p>
    <h2>Sociality</h2>
    <p></p>
    <h2>Nest</h2>
    <p></p>
    <div id="refs" class="references">
      --
      <br>More information:
      <br> <!-- <a href="https://bugguide.net/node/view/70932">Bug Guide</a> -->
    </div>
  </body>
</html>

我将对 HTML 进行一些更改:

  • 为页面添加标题。
  • 删除不必要的接缝的 MathJax。
  • &lt;h3&gt; 标记转换为&lt;h2&gt;,因为您仅将它用于“相似物种”。更改它还允许在生成 HTML 时使用循环。
  • CSV 中有 2 个链接没有在 HTML 中使用:“Discover Life”“Other”,您不想显示他们 ?我为此添加了代码;-)

好的,首先,您创建一个函数,给定一个 CSV 行,生成相应的 HTML。这里我使用ERB 模板,但您可以直接使用字符串文字(编辑:固定ERB#result Ruby

require 'cgi'
require 'erb'
    
def renderHTML row
  htmlsafe = row.each_with_object({}) { |(k,v),h| h[k] = CGI.escapeHTML v if v }
  template = <<-'EOF'
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title><%= "#{htmlsafe['Genus']} #{htmlsafe['species']}" %></title>
  </head>
  <body>
    <h1><em><%= "#{htmlsafe['Genus']} #{htmlsafe['species']}" %></em> - <%= htmlsafe['Common name'] %></h1>
<% for key in ['Status','Info','Time of year this bee is seen','Identification','Similar Species','Flowers','Sociality','Nest'] %>
    <h2><%= key %></h2>
    <p><%= htmlsafe[key] %></p>
<% end %>
    <div id="refs" class="references">
      --
      <br>More information:
<% for key in ['Bug Guide', 'Discover Life', 'Other'].select{ |k| htmlsafe[k] } %>
      <br><a href="<%= htmlsafe[key] %>"><%= key %></a>
<% end %>
    </div>
  </body>
</html>
EOF
  #ERB.new(template, trim_mode: "<>").result(binding) # NOTE: only for Ruby >= 2.4.0
  ERB.new(template, nil, "<>").result(binding)
end

然后您可以在读取 CSV 文件的每一行时调用上一个函数:

require 'csv'
    
filepath = 'bee_key_fact_sheet.csv'
    
CSV.foreach(filepath, headers: true) do |row|
  filename = "#{row['Genus']}_#{row['species']}.html".tr("\0/",'')
  html = renderHTML row
  puts "\n# #{filename}\n#{html}"
  #File.write(filename, html)
end

注意:我注释掉了将创建 HTML 文件的 File.write 行。

【讨论】:

  • 在提供答案之前更好地理解问题不是更有意义吗?
【解决方案2】:

你可以试试这个吗?它应该是读取文件行

f = File.new("name_of_file")
f.each_line { |line| puts line }

您可以稍后将它们保存为新文件,更多信息请点击此处: How to create a file in Ruby

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 2021-08-10
    • 2015-11-14
    相关资源
    最近更新 更多