我尝试在此Elixir代码中调用String.replace
,该代码从structs
列表中获取其值,但这只会导致运行时错误。
String.replace函数的字符串参数全部打印出来,一切正常。为什么会这样?
以下是导致错误的行:
Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> String.replace(sslCmd, "{{#{x.key}}}", x.value) end)
# Runtime error here
** (ArgumentError) argument error
(stdlib) binary.erl:275: :binary.replace/4
(elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/code.ex:363: Code.require_file/2
这是完整的代码:
defmodule ParamStruct do
defstruct key: "", value: "", default: "", description: "description of parameter", label: "label on web form", required: false, order: 99
end
defmodule TemplateStruct do
defstruct key: "must be unique", name: "descriptive name", code: "", executable: false, destination: "", delete_after: false,
perms: "644"
end
defmodule ProcessList do
def parse_list([]), do: []
def parse_list([%{"key" => ky,"value" => val,"default" => dft, "description" => desc,"label" => lbl} | tail]) do
[%ParamStruct{key: ky, value: val, description: desc, label: lbl, default: dft } | parse_list(tail) ]
end
def create_recommend_list(%{"itemScores" => score_list}) do
parse_list(score_list)
end
end
params = [
%{"key" => "ca_cert_subj_state","value" => "Greater London","default" => "Greater London","description" => "Region","label" => "State/County"},
%{"key" => "key-file","value" => "cacert_001","default" => "cacert_001","description" => "","label" => "Key File (without password)"},
%{"key" => "key-file-pass","value" => "cacert_pass_001","default" => "cacert_pass_001","description" => "","label" => "Key File (with password)"},
%{"key" => "ca_cert_email","value" => "admin@domain.net","default" => "admin@domain.net","description" => "","label" => "Email"},
%{"key" => "ca_cert_subj_common_name","value" => "Elixir User","default" => "domain.net","description" => "","label" => "Common Name"},
%{"key" => "ca_cert_subj_country","value" => "UK","default" => "UK","description" => "Country","label" => "Country"},
%{"key" => "ca_cert_subj_location","value" => "Manchester","default" => "Westchester","description" => "","label" => "Location"},
%{"key" => "ca_cert_subj_organization","value" => "Elixir Programs Forum","default" => "Big Company","description" => "","label" => "Organisation"},
%{"key" => "ca_cert_subj_org_unit","value" => "IT Department","default" => "Infosystems and Communications","description" => "","label" => "Organisational Unit"}
]
sslCmd = '''
openssl req -x509 -new -nodes -sha256 \
-key {{key-file-pass}}.key \
-days 3650 \
-out {{key-file-pass}}.pem \
-subj "\
/C={{ca_cert_subj_country}}\
/ST={{ca_cert_subj_state}}\
/L={{ca_cert_subj_location}}\
/O={{ca_cert_subj_organization}}\
/OU={{ca_cert_subj_org_unit}}\
/CN={{ca_cert_subj_common_name}}\
/emailAddress={{ca_cert_email}}\
'''
structList = ProcessList.parse_list(params)
#IO.inspect ProcessList.parse_list(params)
# [first | _ ] = ProcessList.parse_list(params)
# IO.puts " #{first.key} is #{first.value} "
# IO.inspect first
IO.puts sslCmd
IO.puts "list of keys and values"
IO.puts "======================="
Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> IO.puts " #{x.key} is #{x.value} " end)
Enum.reduce(structList, sslCmd, fn(x, sslCmd) -> String.replace(sslCmd, "{{#{x.key}}}", x.value) end)
# Runtime error here
** (ArgumentError) argument error
(stdlib) binary.erl:275: :binary.replace/4
(elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/code.ex:363: Code.require_file/2
答案 0 :(得分:1)
您的问题是,sslCmd
是Char List, not a String,这就是您无法在其上调用String.replace
的原因(仅适用于字符串a.k.a二进制文件)。
最简单的解决方案是将sslCmd
的值更改为:
sslCmd = """
openssl req -x509 -new -nodes -sha256 \
-key {{key-file-pass}}.key \
-days 3650 \
-out {{key-file-pass}}.pem \
-subj ""\
/C={{ca_cert_subj_country}}\
/ST={{ca_cert_subj_state}}\
/L={{ca_cert_subj_location}}\
/O={{ca_cert_subj_organization}}\
/OU={{ca_cert_subj_org_unit}}\
/CN={{ca_cert_subj_common_name}}\
/emailAddress={{ca_cert_email}}\
"""
(注意双引号"""
而不是单引号'''
)