【问题标题】:How can I edit a ruby file (Rakefile) in place from within ruby?如何从 ruby​​ 中编辑 ruby​​ 文件(Rakefile)?
【发布时间】:2017-10-21 18:30:01
【问题描述】:

我不确定问题标题是否有意义,但这就是我想要做的。

我有一个包含数组的 Rakefile。我希望能够使用另一个 ruby​​ 脚本来读取 Rakefile,向该数组添加一些内容,对其进行排序,然后将其写回 Rakefile。

在伪代码中,这就是我想要实现的目标:

rake_file = load file('Rakefile')
rake_file.array += 'new data'
rake_file.array.sort!
file.write Rakefile

Rakefile 包含许多数组和任务,因此我不能将其视为常规文本文件,而只是将值附加到文件并进行排序,因此我的想法是加载它并如上所述编辑数组。

这可能吗?

【问题讨论】:

    标签: arrays ruby rakefile


    【解决方案1】:

    我不能把它当作普通的文本文件来对待

    然后您需要学习 ANTLR,创建 Ruby 语法,生成解析器,并编写 Java 或 C# 或 Python tree walker 来编辑您的数组。简单:-)

    我设想了一个快速简单的解决方案。数组保存在一个文件中,比如array_source.rb

        a = [1, 5, 10, 15]
    

    此文件可以手动编辑,或者,如果您需要以编程方式生成数据,可以使用脚本创建,例如 create_array_source.rb:

    # update the file containing the array of data in text representation
    
    array_source_name = 'array_source.rb'
    
    a = [1, 5, 10, 15]
    # add new data
    [2, 6, 11, 16].each { | e | a << e }
    puts a.join(' ')
    
    # Write it to a file
    File.open(array_source_name, 'w') do | out |
        # to avoid a very long single line, the data is pretty printed
        groups = []
        a.sort.each_slice(4) { | slice | groups << slice.join(', ') }
        out.puts '    ['
        out.print '     '
        out.puts groups.join(",\n     ")
        out.puts '    ]'
    end
    
    puts "#{array_source_name} has been created"
    

    执行:

    $ ruby -w create_array_source.rb 
    1 5 10 15 2 6 11 16
    array_source.rb has been created
    

    文件array_source.rb之后:

        [
         1, 2, 5, 6,
         10, 11, 15, 16
        ]
    

    在 Rakefile 中,要更新的数组放置在两个特定标记之间:

    task :default => [:ta, :tb] do
    end
    
    task :ta do
        # $$insert array after$$
        a = [1, 5, 10, 15]
        # $$insert array before$$
        # do something with a
    end
    
    task :tb do
        # do something
    end
    

    所以很容易编写一个脚本来处理它作为一个文本文件,将行分成两部分:

    • 从开头到“插入”标记
    • 从“插入之前”标记到末尾

    然后通过连接第一部分、数组和第二部分来重写文件:

    # modify a specific array in a Rakefile
    
    rakefile_name     = 'Rakefile'
    array_source_name = 'array_source.rb'
    lines = IO.readlines(rakefile_name)
    insert_marker_after_seen  = false
    insert_marker_before_seen = false
    lines1 = []
    lines2 = IO.readlines(array_source_name)
    lines3 = []
    
    # split the Rakefile
    lines.each do | line |
        case
        when insert_marker_after_seen == false
            lines1 << line
    
            if line.include?('$$insert array after$$')
            then
                insert_marker_after_seen = true
            end
        when ! insert_marker_before_seen
            # ignore array lines
    
            if line.include?('$$insert array before$$')
            then
                insert_marker_before_seen = true
                lines3 << line
            end
        else
            lines3 << line
        end
    end
    
    # Rewrite the Rakefile
    File.open(rakefile_name, 'w') do | out |
        [ lines1, lines2, lines3 ].each do | lines_group |
            lines_group.each { | line | out.puts line }
        end
    end
    
    puts "#{rakefile_name} has been updated with #{array_source_name}"
    

    执行:

    $ ruby -w modify_rakefile.rb 
    Rakefile has been updated with array_source.rb
    

    Rakefile 之后:

    task :default => [:ta, :tb] do
    end
    
    task :ta do
        # $$insert array after$$
        [
         1, 2, 5, 6,
         10, 11, 15, 16
        ]
        # $$insert array before$$
        # do something with a
    end
    
    task :tb do
        # do something
    end
    

    【讨论】:

    • 我喜欢这个想法,但是它并不能解决保持数组排序的问题,而且还会在 Rakefile 中添加一些标记。也许将 rakefile 加载到内存中,在读取数组后编辑数组,然后重写整个文件呢?
    • 我花了 4 个小时来准备这个答案。你读过它吗 ?数组在create_array_source.rb 中排序,在File.open ... 中由a.sort... 排序。 Makefile 被加载到内存中:lines = IO.readlines(rakefile_name)。该文件被完全重写。您想如何在不使用解析器解析 Ruby 代码或使用标记技巧的情况下编辑数组?您可以使用if line.include?('&lt;array name&gt;'),但数组必须具有唯一的名称/位置。我让您自己想象其他解决方案。
    • 我的错,我看错了它的顺序。感谢您在这方面的努力,我一定会试一试的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 2015-05-21
    相关资源
    最近更新 更多