我想尝试使用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文本文件时,我看到了正确的结果
现在在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文件时,它显示为
使用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)
现在文件是
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
查看写入的文件,它与原始字符串不同:
现在与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()
这是输出
以上是我想从Ruby获得的内容。
答案 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)
如果您希望完全避免使用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'"""