mruoss
Is there a way to escape escape characters i.e. turn `"\u2003"` => `"\\u2003"`?
Hey, does anybody know if it is possible to escape escape characters like \r or \u2003? Given a string containing such characters, I’d like to turn them into an escaped form as follows:
iex> Magic.escape("\r\u2003")
"\\r\\u2003"
First Post!
dimitarvp
The only thing that I am aware of after 5 minutes of searching is Regex.escape/1.
And it only covers part of these: Escape characters.
Most Liked
Eiji
All you need to do is to define a list of characters you want to escape and the rest is a simple reduce:
defmodule Example do
@characters_to_escape [?b]
def sample(string) when is_binary(string) do
for <<char::utf8 <- string>>, reduce: "" do
acc -> acc <> maybe_escape(char)
end
end
defp maybe_escape(char) when char in @characters_to_escape do
char
|> Integer.to_string(16)
|> String.pad_leading(4, "0")
|> then(&"\\u" <> &1)
end
defp maybe_escape(char), do: <<char::utf8>>
end
iex> Example.sample("a b c")
"a \\u0062 c"
Eiji
mruoss
Thank you all for the input and the sparring. @Eiji I guess I was hoping for some well-defined distinction / function to tell “printable” from other unicode chars. But I learned that what needs to be escaped depends very much on the use case. Looking at Jason, there is the :escape option which can be one of 4 possible values, each one escaping more or fewer chars.
I think the problem is that what you are asking for doesn’t make sense.
@adamu Yes, that too, probably! ![]()
Inspired by Jason I ended up with something like the following which works for my case for now (probably needs refinement):
defmodule NotSoMuchMagic do
@escape_chars '\b\f\r\v\"\\'
@escape_char_maping Enum.zip('\b\f\r\v\"\\', 'bfrv"\\')
@unicode_char_mapping 0x00..0x1F |> Enum.reject(&Kernel.in(&1, '\n\t'))
for {src, dst} <- @escape_char_maping do
defp encode_char(unquote(src)), do: [?\\, unquote(dst)]
end
for uchar <- @unicode_char_mapping do
unicode_sequence = List.to_string(:io_lib.format("\\u~4.16.0B", [uchar]))
defp encode_char(unquote(uchar)), do: unquote(unicode_sequence)
end
defp encode_char(char), do: char
def encode(binary) do
iodata = for (<< char::utf8 <- binary >>), do: encode_char(char)
IO.iodata_to_binary(iodata)
end
end
iex> NotSoMuchMagic.encode("\r \t \v \0 \u0028 \u0012")
"\\r \t \\v \\u0000 ( \\u0012"
Last Post!
mruoss
Yes, that’s almost exactly what I’m doing in the PR linked above. However, there are some things to consider. Let’s take char \u0085. It has an escape character in YAML (\N). But it is also in the c-printable range. So while theoretically it can be left alone, I preferred to encode it as \N because I think it is editor/reader friendlier. Would you agree? So my order is…
- Is \n or \t or? Leave it alone
- Has c escape? Convert to that.
- In printable range? Leave it alone.
- Escape with \u
Printing to console:
iex> IO.puts("a\u0085b")
a
b
:ok
Decode YAML (escape char inside double quotes) and printing to console:
iex> ~s("a\\Nb") |> YamlElixir.read_from_string!() |> IO.puts
a
b
:ok
Decode YAML (actual character) and printing to console:
iex> "a\u0085b" |> YamlElixir.read_from_string!() |> IO.puts
a
b
:ok
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









