代码之家  ›  专栏  ›  技术社区  ›  Fravadona

Ruby为POSIX shell编写带转义的TSV

  •  0
  • Fravadona  · 技术社区  · 4 年前

    我在找 简明的 输出TSV记录的方法,这些记录可以用POSIX外壳精确读取和取消扫描( IFS='<TAB>' read -r + printf %b )。

    最低限度的转义规则是:

    • \\ 用于反斜杠
    • \n 用于换行符
    • \t 用于选项卡
    • \r 用于回车

    但它们可以扩展到 full supported set 属于 printf ,如果有一种简单的方法可以用ruby实现的话。

    迄今为止的代码:

    record = [ "\\", "\t", "\n", "\r", "\"" ]
    
    rules = {
      "\\" => "\\\\",
      "\t" => "\\t",
      "\r" => "\\r",
      "\n" => "\\n"
    };
    
    regex = /#{ rules.keys.map{|c| Regexp.escape(c)}.join(?|) }/;
    
    puts record.map { |field| field.gsub(regex) {|c| rules[c]} }.join("\t")
    

    输出:

    \\  \t  \n  \r  "
    

    主要的问题是,代码是针对一行代码的,因此,如果可能的话,我想大大减少它。有什么想法吗?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Jörg W Mittag    4 年前

    在Ruby中,每个程序都可以写成一行,因为换行符是可选的:换行符可以具有的每个函数(表达式分隔符、引入语法块等)也可以由符号(例如。 ; 作为表达式分隔符)或关键字(例如。 then 用于引入条件表达式的结果块,或者 case 表达式或 do 介绍的主体 while for 环路等)

    例如,您的代码可以写成一行代码,如下所示:

    record = [ "\\", "\t", "\n", "\r", "\"" ]; rules = { "\\" => "\\\\", "\t" => "\\t", "\r" => "\\r", "\n" => "\\n" }; regex = /#{ rules.keys.map{|c| Regexp.escape(c)}.join(?|) }/; puts record.map { |field| field.gsub(regex) {|c| rules[c]} }.join("\t")
    

    但是,我们可以对代码进行一些可能的改进。

    使用 Regexp::union 建造 regex :

    regex = Regexp.union(rules.keys)
    

    既然你已经经历了建造替代品的麻烦 Hash ,为什么不使用的形式 String#gsub 那个 takes a replacement Hash as an argument :

    puts record.map { |field| field.gsub(regex, rules) }.join("\t")
    
    推荐文章