Converting a tuple to a string in erlang language - erlang

Tuple={<<"jid">>,Member},
Tuple_in_string=lists:flatten(io_lib:format("~p", [Tuple])),
it gives output as:
"{<<\"jid\">>,\"sdfs\"}"
But i want this output without these slashes like
"{<<"jid">>,Member}"
Any pointers?
I have tried all the answers but at the end with io:format("\"~s\"~n", [Tuple_in_string]). what am geeting is "{<<"jid">>,Member}" but it is not a string.it is a atom.I need string on which i can apply concat operation.Any pointers?

You can print it like this:
io:format("\"~s\"~n", [Tuple_in_string]).
It prints:
"{<<"jid">>,"sdfs"}"

The \ are here to denote that the following " is part of the string and not a string delimiter. they do not exist in the string itself. They appear because you use the pretty print format ~p. If you use the string format ~s they wont appear in the display.
1> io:format("~p~n",["a \"string\""]).
"a \"string\""
ok
2> io:format("~s~n",["a \"string\""]).
a "string"
ok
3> length("a \"string\""). % is 10 and not 12
10

Firstly, you don't need to flatten the list here:
Tuple_in_string=lists:flatten(io_lib:format("~p", [Tuple])),
Erlang has the concept of iodata(), which means that printable things can be in nested lists and most functions can handle them, so you should leave only:
Tuple_in_string = io_lib:format("~p", [Tuple]),
Secondly, when you use ~p, you tell Erlang to print the term in such way, that it can be copied and pasted into console. That is why all double quotes are escaped \". Use ~s, which means "treat as string".
1> 38> Tuple = {<<"jid">>,"asdf"}.
{<<"jid">>,"asdf"}
2> IODATA = io_lib:format("~p", [Tuple]).
[[123,[[60,60,"\"jid\"",62,62],44,"\"asdf\""],125]]
3> io:format("~s~n", [IODATA]).
{<<"jid">>,"asdf"}
ok

L = Packet_in_tuple_form={xmlel,<<"message">>,[{<<"id">>,<<"rkX6Q-8">>},{<<"to">>,<<"multicast.devlab">>}],[{xmlel,<<"body">>,[],[{xmlcdata,"Hello"}]},{xmlel,<<"addresses">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/address">>}],[{xmlel,<<"address">>,[{<<"type">>,<<"to">>},"{<<\"jid\">>,\"sds\"}",{<<"desc">>,"Description"}],[]}]}]}.
Gives me:
{xmlel,<<"message">>,
[{<<"id">>,<<"rkX6Q-8">>},{<<"to">>,<<"multicast.devlab">>}],
[{xmlel,<<"body">>,[],[{xmlcdata,"Hello"}]},
{xmlel,<<"addresses">>,
[{<<"xmlns">>,<<"http://jabber.org/protocol/address">>}],
[{xmlel,<<"address">>,
[{<<"type">>,<<"to">>},
"{<<\"jid\">>,\"sds\"}",
{<<"desc">>,"Description"}],
[]}]}]}
The \ in the address field are escape characters.
You can verify the same by checking the length of string.

Related

How to print an empty string in Erlang

I want to print an empty string like this one "", but erlang gives an empty list [].
I tried with some options ~s, ~w from the io, io_lib modules and it doesnt work.
io_lib:format("~s",[""]).
-> [[]]
io_lib:format("~s",['']).
-> []
io:format("~p",[""]).
-> []
Can anyone show me the proper way to get "" as output?
It mostly depends on what you understand as printing an empty string.
In Erlang, an empty string is equivalent to an empty list. So, if you try to just print it, you'll get that:
1> AnEmptyString = "".
[]
2> io:format("~p~n", [AnEmptyString]).
[]
ok
If you want to print the string that is empty… well… since it's empty, it has no characters, therefore…
3> io:format(">~s<~n", [AnEmptyString]).
><
ok
So, if you want to just print two consecutive double quotes, you'll have to just do that by hand:
4> io:format("~s~n", ["\"\""]).
""
ok
Just keep in mind that you're not printing an empty string there, you're printing a string with just two double quotes 🤷‍♂️
This is not pretty, but you need to put characters explicitly in case of an empty string. Does this work for you ?
6> io:format("~s~n", [fun([]) -> "\"\"";(S) -> S end("")]).
""
ok
7> io:format("~s~n", [fun([]) -> "\"\"";(S) -> S end("\"non-empty string\"")]).
"non-empty string"
ok
8>
The Erlang don't have a type as string, please see a documentation - http://erlang.org/doc/reference_manual/typespec.html. But if you want output something like "", you can try use character adaptation like "\"\"" in io lib, but if you will try know the type of what you try output you will get the same type as list. Eg:
1> [H|T] = io_lib:format("~p~n", ["\"\""]).
["\"\\\"\\\"\"",10]
is_list(H).
true
2>

Query from ejabberd module with LIKE %%

I have this lines of code in ejabberd module, it works fine:
case catch ejabberd_odbc:sql_query(Server,["select COUNT(*) as total from spool where username='",IdUsername,"' AND xml LIKE '%message from%' AND xml LIKE '%chat%';"]) of
{selected, [<<"total">>], [[Totale]]} ->
Count = binary_to_list(Totale);
_ -> Count = "0"
end,
If I convert this:
LIKE '%chat%';
with this:
LIKE '%type=\'chat\'%';
I obtain an error, any ideas? or there's another way to get only the chat message?
Since you're typing this in an Erlang string, the Erlang escape sequences apply. In particular, \' is an escape sequence for just a single quote, '. (That's more useful inside atoms, which are delimited by single quotes.)
You can try it in an Erlang shell, and see that "\'" and "'" are equivalent:
1> "\'".
"'"
2> "\'" =:= "'".
true
To include an actual backslash in the string, escape it with another backslash:
"\\'"
In your case, that would be:
LIKE '%type=\\'chat\\'%';

How can i parse the standard input with the erlang api?

I'm developing a game in Erlang, and now i need to read the standard input. I tried the following calls:
io:fread()
io:read()
The problem is that i can't read a whole string, when it contains white spaces. So i have the following questions:
How can i read the string typed from the user when he press the enter key? (remember that the string contains white spaces)
How can i convert a string like "56" in the number 56?
Read line
You can use io:get_line/1 to get string terminated by line feed from console.
3> io:get_line("Prompt> ").
Prompt> hello world how are you?
"hello world how are you?\n"
io:read will get you erlang term, so you can't read a string, unless you want to make your users wrap string in quotes.
Patterns in io:fread does not seem to let you read arbitrary length string containing spaces.
Parse integer
You can convert "56" to 56 using erlang:list_to_integer/1.
5> erlang:list_to_integer("56").
56
or using string:to_integer/1 which will also return you the rest of a string
10> string:to_integer("56hello").
{56,"hello"}
11> string:to_integer("56").
{56,[]}
The erlang documentation about io:fread/2 should help you out.
You can use field lengths in order to read an arbitrary length of characters (including whitespace):
io:fread("Prompt> ","~20c").
Prompt> This is a sentence!!
{ok,["This is a sentence!!"]}
As for converting a string (a list of characters) to an integer, erlang:list_to_integer/1 does the job:
7> erlang:list_to_integer("645").
645
Edit: try experimenting with io:fread/2, the format sequence can ease the parsing of data by applying some form of pattern matching:
9> io:fread("Prompt> ","~s ~s").
Prompt> John Doe
{ok,["John","Doe"]}
The console is not really a good place to do your stuff, because you need to know in advance the format of the answer. Considering that you allow spaces, you need to know how many words will be entered before getting the answer. Knowing that, you can use a string as entry, and then parse it later:
1> io:read("Enter a text > ").
Enter a text > "hello guy, this is my answer :o)".
{ok,"hello guy, this is my answer :o)"}
2>
The bad news is that the user must enter the quotes and a final dot, not user friendly...

Erlang - io:format 's result / (formatting with io_lib:format/2)

I'm trying to get the result of the output of io:format/1.
I know that there's a similar function in io_lib, io_lib:format/2, but the output is different. In fact, it doesn't do anything at all.
If I try to bound io:format, ok is bounded, and the formatted string is written out to the console.
So my question is, how can I get the same output with io_lib:format/2?
Or how can I bound the formatted string to a variable?
1> A = io:get_line('> ').
> "test".
"\"test\".\n"
2> io:format(A).
"test".
ok
3> B = io_lib:format(A, []).
"\"test\".\n"
4> B.
"\"test\".\n"
5> C = io:format(A).
"test".
ok
6> C.
ok
io_lib:format is not an output function the way io:format is. Instead io_lib:format only returns the value, but does not output it.
The result of io:format that you see as "test." is the rendered version as sent to the terminal (including the newline) , then it returns ok. Conversely, the return value of io_lib:format that you see as "\"test\".\n" is simply the erlang shell's representation of the same string, with the quotes and newline escaped, and surrounded by its own quotes.
io_lib:format is more commonly used for inserting values into the strings (similar to C's printf functions). For example, doing something like
NewString = io_lib:format("The string entered was ~s I hope you like it",[A])
The value of NewString would be
The string entered was "test".
I hope you like it
For which the Erlang Shell's representation would be:
"The string entered was \"test\".\n I hope you like it"
If all you want to do is output the value you just entered, then io:format is sufficient for your needs.

splitting of binaries

I tried to split two fields from a binary string:
-define(S,<<"M\0\0\0522039355099,010100000008,0,010170000000,0,0,0,0,0,0,,,0,0,,‌​0110,00,150,0,0,0\0">>).<<Message_length:4/binary,Msg/binary>> = S.
the first 4 bytes are the length of the following message, the other byte are the message,
a null byte terminates the string.
The result is:
** exception error: o match of right hand side value
EDIT
Just before the given code, there is:
[Sequence|Reste] = binary:split(T,<<"\0">>),
Does "Reste" bounded ?
Your code is ok, so either you dont have a binary string, or the length of Mystring does not comply with the pattern. Here's a quick test:
1> Mystring = <<"abcde">>.
<<"abcde">>
2> <<Message_length:4/binary,Msg/binary>> = Mystring.
<<"abcde">>
3> Message_length.
<<"abcd">>
4> Msg.
<<"e">>
If you have a string (a list of integers) instead of a binary string (<<"string">>), as Vincenzo suggested, call erlang:list_to_binary/1 first.
Hope it helps
EDIT: I've checked the example string you left in a comment of Vincenzo's answer. I've tried it with your code and still works. Is it possible that Message_length and/or Msg are already bound (and different to Mystring) when reaching that line of code? That would make the pattern matching fail.
EDIT2: Tested with the updated data in the question:
1> S = <<"M\0\0\0522039355099,010100000008,0,010170000000,0,0,0,0,0,0,,,0,0,,\342\200\214\342\200\2130110,00,150,0,0,0\0">>.
<<77,0,0,42,50,48,51,57,51,53,53,48,57,57,44,48,49,48,49,
48,48,48,48,48,48,48,56,44,48,...>>
2> <<Message_length:4/binary,Msg/binary>> = S.
<<77,0,0,42,50,48,51,57,51,53,53,48,57,57,44,48,49,48,49,
48,48,48,48,48,48,48,56,44,48,...>>
3> Message_length.
<<77,0,0,42>>
4> Msg.
<<"2039355099,010100000008,0,010170000000,0,0,0,0,0,0,,,0,0,,\342"...>>
There is issue with erlang string escape interpolation. The fourth byte is not interpolated as "\0" but "\052".
1> Bin = <<"M\0\0\0522039355099,010100000008,0,010170000000,0,0,0,0,0,0,,,0,0,,0110,00,150,0,0,0\0">>.
<<77,0,0,42,50,48,51,57,51,53,53,48,57,57,44,48,49,48,49,
48,48,48,48,48,48,48,56,44,48,...>>
So you have to write it in this manner.
2> f().
ok
3> Bin = <<"M\0\0\0","522039355099,010100000008,0,010170000000,0,0,0,0,0,0,,,0,0,,0110,00,150,0,0,0\0">>.
<<77,0,0,0,53,50,50,48,51,57,51,53,53,48,57,57,44,48,49,
48,49,48,48,48,48,48,48,48,56,...>>
Then usual way to parse this form of messages is:
4> <<L:32/little,Rest/binary>> = Bin.
<<77,0,0,0,53,50,50,48,51,57,51,53,53,48,57,57,44,48,49,
48,49,48,48,48,48,48,48,48,56,...>>
5> L.
77
6> <<Msg:L/binary,R/binary>> = Rest.
<<"522039355099,010100000008,0,010170000000,0,0,0,0,0,0,,,0,0,,0110,00,150,0,0,0"...>>
7> R.
<<0>>
8> Msg.
<<"522039355099,010100000008,0,010170000000,0,0,0,0,0,0,,,0,0,,0110,00,150,0,0,0">>
You have to call list_to_binary/1 on string to be matched.
If you have further problems, type example string please!

Resources