如何在Ruby中使用HERE-DOCUMENT语法创建多行字符串文字?

时间:2015-06-27 23:28:39

标签: ruby string

问题摘要

我想尝试使用Ruby来完成我在Python中所做的事情。在Python中它有r""" syntax to support raw strings,这很好,因为它允许一个原始字符串与代码一致,并以更自然的方式连接它们,并且不需要特殊的缩进。在Ruby中,当使用原始字符串时,必须在单独的行中使用<<'EOT'后跟EOT,这会破坏代码布局。

您可能会问,为什么不使用Ruby的%q{}?好吧,因为%q{}与Python的r"""相比有限制,因为它不会转义多个\\\并且只处理单个\

我正在动态生成Latex代码并写入一个文件,后来用pdflatex编译。 Latex代码在很多地方都包含\\\之类的内容。如果我使用Ruby的%q{}语法,那么它将无效。所以我必须使用Ruby的<<'EOT',但我不想这样做,因为它使得代码更难以在Ruby源文件中读取,因为必须打破它以进行缩进以使EOT满意。

我在问是否有一种方法可以使语法类似于%q{},或者某些函数采用字符串并返回相同的结果,就像使用EOT一样,处理原始字符串而不受限制EOT

我不需要插值。所以单引号字符串。没有双引号。双引号导致插值,我不想要。

用于说明

的小工作示例

这是Python中的一个小例子,然后我展示了我在Ruby中必须做什么来生成相同的输出。

my_file = open("py_latex.tex", 'w')
x = r"""\\\hline is a raw string"""+r""" another one \\\hline and so on"""
my_file.write(x)

当我打开上面写的Latex文本文件时,我看到了正确的结果

Mathematica graphics

现在在Ruby中做同样的事情。我不能写下面的内容(即使我愿意)

file = File.open('rb_latex.tex','w')
x=%q{\\\hline is a raw string}+%q{ another one \\\hline and so on}
file.write(x)

以上所说的不是我想要的。当它写入latex文件时,它显示为

Mathematica graphics

使用EOT有效,如下

file = File.open('rb_latex.tex','w')
x=<<-'EOT1'+<<-'EOT2'
\\\hline is a raw string
EOT1
 another one \\\hline and so on
EOT2
file.write(x)

现在文件是

Mathematica graphics

PS。它使第二个字符串在新行上,这对我来说是个问题,并且在我解决了手头的主要问题之后会尝试找到解决方案。

问题的简短摘要

如何使类似Python的%q{}语法与Python r"""类似?

如果有人想在Ruby中尝试上述代码,请确保EOT之后没有空格。我还在完整的源代码下面添加了。

Python完整源代码

import os
os.chdir(" direct to change to here ")    
my_file = open("py_latex.tex", 'w')
x = r"""\\\hline is a raw string"""+r""" another one \\\hline and so on"""
my_file.write(x)
my_file.close()

Ruby源代码

#!/usr/local/bin/ruby -w
Dir.chdir("/home/....")
file = File.open('rb_latex.tex','w')
#x=%q{\\\hline is a raw string}+%q{ another one \\\hline and so on}
x=<<-'EOT1'+<<-'EOT2'
\\\hline is a raw string
EOT1
 another one \\\hline and so on
EOT2
file.write(x)
file.close

更新

回答以下评论:

这个想法是它应该完全像HERE-DOCUMENT一样,但是使用%q {}的漂亮语法,可以更容易地格式化ruby源代码中的字符串。即,无论是什么,内部的任何内容都应该按原样写入文件。

我测试了下面提供的解决方案,但它并不适用于所有情况。这是一个测试用例:

#!/usr/local/bin/ruby -w    
class String
  def raw
    gsub('\\'*2) { '\\'*3 }
  end
end    
class Array
  def raw(separator = $,)
    map(&:raw).join(separator)
  end
end

Dir.chdir("/home/me")
file = File.open('rb_latex.tex','w')
x=%q{'\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string
            <!DOCTYPE html>
            \[ stuff \]
            <html>
            <head>
            <title>title</title>
            <style>
            video {
              width: 100%    !important;
              eight: auto   !important;
            }
            </html> \"quotes\"    (did you see this?)
            \\\hline $\sin(x)$
            </style>'  //notice this ' is in the raw string!, ok!
            \begin{tabular}{c}\\\hline  '''''' (6 of them)
            x\\\hline
            \end{tabular}}.raw+%q{another '''one \\\hline and so on'}.raw

file.write(x)
file.close

查看写入的文件,它与原始字符串不同:

enter image description here

现在与Python r"""

进行比较
import os
os.chdir("/home/me")    
my_file = open("py_latex.tex", 'w')
x =r"""\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string
            <!DOCTYPE html>
            \[ stuff \]
            <html>
            <head>
            <title>title</title>
            <style>
            video {
              width: 100%    !important;
              eight: auto   !important;
            }
            </html> \"quotes\"    (did you see this?)
            \\\hline $\sin(x)$
            </style>'  //notice this ' is in the raw string!, ok!
            \begin{tabular}{c}\\\hline  '''''' (6 of them)
            x\\\hline
            \end{tabular}}"""+r"""{another '''one \\\hline and so on'"""
my_file.write(x)
my_file.close()

这是输出

enter image description here

以上是我想从Ruby获得的内容。

4 个答案:

答案 0 :(得分:1)

清理此处文件中的缩进

要处理此处文档中的缩进问题,一种方法是对核心String类进行修补,添加实例方法String#undent

class String
  def undent
    indentation = slice(/^\s+/).length
    gsub(/^.{#{ indentation }}/, '')
  end
end

然后你可以像这样重写你的代码:

x = <<-'EOT'.undent
  \\\hline is a raw string
   another one \\\hline and so on
EOT

注意:修补核心类通常被认为是不好的样式,可能会影响稳定性和可维护性。也就是说,我认为修补String以添加#undent是一个明智的例外。这种方法只有很多好处,并不是真正的侵入性 最终,由你来衡量利弊。

答案 1 :(得分:0)

撤消Ruby的转义语法

如果您希望完全避免使用heredocs,并且假设您的常见情况是一系列正好三个\ s,那么如下所示呢?

class String
  def raw
    gsub('\\'*2) { '\\'*3 }
  end
end

class Array
  def raw(separator = $,)
    map(&:raw).join(separator)
  end
end

这引入了一组#raw实例方法来补偿Ruby将前导反斜杠视为转义字符。

实施例

示例a)

x = '\\\hline is a raw string'.raw + ' another one \\\hline and so on'.raw

示例b)

x = %q{\\\hline is a raw string}.raw + %q{ another one \\\hline and so on}.raw

示例c)

x = ['\\\hline is a raw string', ' another one \\\hline and so on'].raw

或者,如果事先设置$, = ' ',您甚至可以取消领先的空间:

示例d)

x = ['\\\hline is a raw string', 'another one \\\hline and so on'].raw

示例e)

x = [%q{\\\hline is a raw string}, %q{ another one \\\hline and so on}].raw

或者,假设您事先设置了$, = ' '

示例f)

x = [%q{\\\hline is a raw string}, %q{another one \\\hline and so on}].raw

结果

对于六个例子a)到f)中的每一个,结果是:

\\\hline is a raw string another one \\\hline and so on

答案 2 :(得分:0)

如果这是一个一次性的数据块,那么Ruby有一个鲜为人知的DATA文件句柄:

#!/bin/env ruby
puts DATA.read
__END__
Hi there, this is data
\\\\quad backslashes are no problem!\\\\

在魔术__END__之后,文件中剩下的任何内容都被视为未转义的字符串数据,可以从名为DATA的文件句柄中读取。

因此,您的脚本可能如下所示:

#!/usr/local/bin/ruby -w
File.open('/home/me/rb_latex.tex','w') {|fp| fp.print DATA.read }
__END__
'\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string
<!DOCTYPE html>
\[ stuff \]
<html>
<head>
<title>title</title>
<style>
video {
  width: 100%    !important;
  eight: auto   !important;
}
</html> \"quotes\"    (did you see this?)
\\\hline $\sin(x)$
</style>'  //notice this ' is in the raw string!, ok!
\begin{tabular}{c}\\\hline  '''''' (6 of them)
x\\\hline
\end{tabular}another '''one \\\hline and so on'

尽管如此,我很好奇:你为什么还要把它作为一个中间的Ruby脚本来生成,它的唯一工作就是把它写到另一个文件中?简单地将输出直接写入目标文件不是更方便吗?

答案 3 :(得分:0)

使用&lt;&lt;&#; EOT&#39;应该得到你想要的东西(注意结束标记上的单引号):

my_file = File.open("/tmp/rb_latex.tex", 'w')
x = <<'EOT'
\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string
            <!DOCTYPE html>
            \[ stuff \]
            <html>
            <head>
            <title>title</title>
            <style>
            video {
              width: 100%    !important;
              eight: auto   !important;
            }
            </html> \"quotes\"    (did you see this?)
            \\\hline $\sin(x)$
            </style>'  //notice this ' is in the raw string!, ok!
            \begin{tabular}{c}\\\hline  '''''' (6 of them)
            x\\\hline
            \end{tabular}}"""+r"""{another '''one \\\hline and so on'"""
EOT

my_file.write(x)
my_file.close()

生成此文件:

cat /tmp/rb_latex.tex
\\'\hline \\\\\\ (6 of them) // some stuff follows. All should be raw string
            <!DOCTYPE html>
            \[ stuff \]
            <html>
            <head>
            <title>title</title>
            <style>
            video {
              width: 100%    !important;
              eight: auto   !important;
            }
            </html> \"quotes\"    (did you see this?)
            \\\hline $\sin(x)$
            </style>'  //notice this ' is in the raw string!, ok!
            \begin{tabular}{c}\\\hline  '''''' (6 of them)
            x\\\hline
            \end{tabular}}"""+r"""{another '''one \\\hline and so on'"""