Здесь документы
Для длинных строковых литералов может не быть отдельного символьного разделителя, который можно было бы использовать, не беспокоясь о том, чтобы не забыть экранировать символы внутри литерала. Решение этой проблемы в Ruby позволяет вам указать произвольную последовательность символов, которая будет служить разделителем для строки. Этот тип литерала заимствован из синтаксиса оболочки Unix и исторически известен как здесь документ . (Поскольку документ находится здесь, в исходном коде, а не во внешнем файле.)
Здесь документы начинаются с <<
или <<-
. За ними сразу же следует (пробел не допускается, чтобы избежать неоднозначности с оператором левого сдвига) идентификатор или строка, которая задает конечный разделитель. Текст строкового литерала начинается со следующей строки и продолжается до тех пор, пока текст разделителя не появится на отдельной строке. Например:
document = <<HERE # This is how we begin a here document
This is a string literal.
It has two lines and abruptly ends...
HERE
Интерпретатор Ruby получает содержимое строкового литерала, читая строку за раз из его ввода. Это не означает, однако, что <<
должен быть последним в своей строке. Фактически, после прочтения содержимого документа здесь, интерпретатор Ruby возвращается к той строке, в которой он находился, и продолжает его анализ. Например, следующий код Ruby создает строку, объединяя два документа здесь и обычную строку в одинарных кавычках:
greeting = <<HERE + <<THERE + "World"
Hello
HERE
There
THERE
<<HERE
в строке 1 заставляет интерпретатор читать строки 2 и 3. А <<THERE
заставляет интерпретатор читать строки 4 и 5. После прочтения этих строк три строковых литерала объединяются в один .
Конечный разделитель документа здесь действительно должен появляться в строке сам по себе: ни один комментарий не может следовать за разделителем. Если здесь документ начинается с <<
, то разделитель должен начинаться с начала строки. Если вместо этого литерал начинается с <<-
, то перед разделителем может быть пробел. Новая строка в начале документа здесь не является частью литерала, но новая строка в конце документа. Поэтому каждый документ здесь заканчивается символом конца строки, за исключением пустого документа здесь, который совпадает с ""
:
empty = <<END
END
Если вы используете без кавычек идентификатор в качестве терминатора, как в предыдущих примерах, то здесь документ ведет себя как строка в двойных кавычках для интерпретации escape-символов обратной косой черты и символа #
. Если вы хотите быть очень, очень буквальным, не допуская использования escape-символов, поместите разделитель в одинарные кавычки. Это также позволяет вам использовать пробелы в вашем разделителе:
document = <<'THIS IS THE END, MY ONLY FRIEND, THE END'
.
. lots and lots of text goes here
. with no escaping at all.
.
THIS IS THE END, MY ONLY FRIEND, THE END
Одинарные кавычки вокруг подсказки-разделителя указывают на то, что этот строковый литерал похож на строку в одинарных кавычках. На самом деле, этот документ здесь еще строже. Поскольку одинарная кавычка не является разделителем, нет необходимости избегать одиночной кавычки с обратной косой чертой. И поскольку обратный слеш никогда не нужен как экранирующий символ, никогда не нужно избегать самого обратного слэша. Следовательно, в этом виде документа обратная косая черта является просто частью строкового литерала.
Вы также можете использовать строковый литерал в двойных кавычках в качестве разделителя для документа here. Это то же самое, что использование одного идентификатора, за исключением того, что он допускает пробелы внутри разделителя:
document = <<-"# # #" # This is the only place we can put a comment
<html><head><title>#{title}</title></head>
<body>
<h1>#{title}</h1>
#{body}
</body>
</html>
# # #
Обратите внимание, что нет способа включить комментарий в документ здесь, кроме как в первой строке после токена <<
и до начала литерала. Из всех #
символов в этом коде один вводит комментарий, три интерполирующих выражения в литерал, а остальные - разделитель