2016-08-20 1 views
0

Imagine У меня есть 2 файла:рубин Возвращает содержимое текстового файла (.txt) после замены переменных

A.txt 

This is a sentence with a #{variable}. 

и сценарий рубиновый.

Iamascript.rb 

... 
variable = "period" 
... 

Есть ли способ, что я могу прочитать содержимое файла .txt и вставить переменную перед puts'ing его? Это означает, что мой выход при выполнении радиоканала-скрипт должен быть

This is a sentence with a period. 

файл .txt является динамическим.

ответ

2

Что вы ищете обычно называют шаблонный, и вы в основном определили язык шаблона. Ruby фактически отправляет в стандартную библиотеку язык шаблонов под названием ERb, поэтому, если вы хотите немного изменить синтаксис своего языка шаблонов, вы можете просто использовать это вместо того, чтобы придумывать свои собственные:

a.txt:

This is a sentence with a <%=variable%>. 

Iamascript.rb

require 'erb' 

variable = 'period' 

puts ERB.new(File.read('A.txt')).result(binding) 
# This is a sentence with a period. 
+0

Спасибо, это работает как очарование для меня. Можно ли также прочитать хэш из внешнего файла .txt или .rb и использовать его ключи (и значения) в «главном» -коде с этим? – Phero

+0

Если вы хотите читать чистые данные без какого-либо поведения, гораздо лучше (и более простые * и * безопасные) использовать для этого чистый язык описания данных, а не язык программирования. (И, в конце концов, ERb позволяет вставлять * произвольный * Ruby-код, включая, но не ограничиваясь, код, который удаляет все ваши данные, форматирует ваш жесткий диск, запускает бэкдор и т. Д.) Если вы хотите только читать данные , используйте язык данных, такой как XML, YAML или JSON. (Я бы предпочел JSON или YAML, а не XML. Зависит от аудитории, то есть людей, которым придется редактировать этот файл.) –

+0

Проект не касается чистого извлечения данных, использование шаблонов было бы просто удобством. Мне просто нравится использовать шаблон для некоторых фрагментов кода, чтобы иметь несколько (разных) выходов без необходимости перекодировать все. Но если вы говорите, что это проблема безопасности, я буду менять свой код каждый раз. – Phero

0

Существует одно «очевидное» (но плохое) решение, которое будет иметь значение. eval запускает бит кода, который вы ему даете.

Это проблема безопасности, но может быть то, что вы ищете, если хотите, если вам нужны сложные выражения в #{...}.

Более правильный способ сделать это, если вы даже немного позаботились о безопасности, - это использовать оператор форматирования Ruby: % (аналогично Python's).

template = "the variable's value is %{var}" 
puts template % {var: "some value"} => prints "the variable's value is some value" 
0

Предположим, что файл "A.txt" содержит одну строку текста (или эта строка извлекается из файла):

s1 = 'This is a sentence with a #{my_var}' 

и второй файл, "Iamascript.rb", содержит:

s2 =<<_ 
line of code 
    line of code 
    my_var = "period" 
    line of code 
line of code 
_ 
    #=> "line of code\n line of code\n my_var = 'period'\n line of code\nline of code\n" 

Давайте создадим эти файлы:

File.write("A.txt", s1) 
    #=> 35 
File.write("Iamascript.rb", s2) 
    #=> 78 

Теперь прочитайте первую строку "A.txt" и извлеките начало строки "\#{" и закончите "}", затем извлеките имя переменной из этой строки.

r1 =/
    \#\{ # match characters 
    [_a-z]+ # match > 0 understores or lower case letters 
    \}  # match character 
    /x  # free-spacing regex definition mode 

s1 = File.read("A.txt") 
    #=> "This is a sentence with a #{my_var}" 
match = s1[r1] 
    #=> "\#{my_var}" 
var_name = match[2..-2] 
    #=> "my_var" 

Теперь прочитайте «Iamascript.rb» и найдите строку, которая соответствует следующему регулярному выражению.

r2 =/
    \A   # match beginning of string 
    #{var_name} # value of var_name 
    \s*=\s*  # match '=' and surrounding whitespace 
    ([\"'])  # match a single or double quote in capture group 1 
    ([^\"']+) # match other than single or double quote in capture group 2 
    ([\"'])  # match a single or double quote in capture group 3 
    \z   # match end of string 
    /x   # free-spacing regex definition mode 
#=>/
# \A   # match beginning of string 
# my_var  # value of var_name 
# \s*=\s*  # match '=' and surrounding whitespace 
# ([\"'])  # match a single or double quote in capture group 1 
# ([^\"']+) # match other than single or double quote in capture group 2 
# ([\"'])  # match a single or double quote in capture group 3 
# \z   # match end of string 
# /x 

Если обнаруживается совпадение возвращает строку из "A.txt" с текстом замены, иначе вернуть nil.

if File.foreach("Iamascript.rb").find { |line| line.strip =~ r2 && $1==$3 } 
    str.sub(match, $2)  
else 
    nil 
end 
    #=> "This is a sentence with a period"