0
$\begingroup$

ToString[exp] results in the string form of the evaluated form of exp when exp contains Prefix (@), such as when exp is an email address. How can such an expression be converted to a string?

$\endgroup$
4
  • 2
    $\begingroup$ …Why not simply "[email protected]"? $\endgroup$
    – xzczd
    Commented Apr 30 at 3:52
  • 3
    $\begingroup$ Why wouldn't the email already be a string? $\endgroup$
    – lericr
    Commented Apr 30 at 3:53
  • 1
    $\begingroup$ You're bumping up against core parsing functionality. The @ gets immediately parsed into a headed expression. You might be better off post-processing the string after ToString[exp]. I.e. insert the"@" and remove the brackets and spaces. $\endgroup$
    – lericr
    Commented Apr 30 at 4:03
  • 1
    $\begingroup$ This is one of those questions where the right answer is "Why do you want to do that? Stop it" $\endgroup$
    – Jason B.
    Commented May 1 at 14:15

2 Answers 2

1
$\begingroup$

The problem here is that notation like f @ x doesn't exist on the expression level; there's no difference between f[x] and f @ x. In order to do anything sensible here, you'd have to work on the boxes level. Here is a method for intercepting boxes directly from the input cell and converting them to a string. First define a head HoldBoxes that acts as a special token for MakeExpression:

MakeExpression[
  RowBox[{"HoldBoxes", "[", boxes_, "]"}],
  form : StandardForm
] := HoldComplete[boxes]

Now you can type things inside HoldBoxes and you'll get an expression back with those boxes:

HoldBoxes[[email protected]]

RowBox[{"my", ".", RowBox[{"name", "@", "yahoo"}], ".", "com"}]

The next step is to convert the boxes to a string, which is something you can do with some FE magic:

boxesToString[boxes_] := Replace[
  UsingFrontEnd[
   FrontEndExecute[
    FrontEnd`ExportPacket[BoxData[boxes], "PlainText"]]],
  {
   {s_String, ___} :> s,
   _ :> $Failed
   }
  ]

now you can type the email address without strings around it, though you obviously still need to wrap things in HoldBoxes:

boxesToString @ HoldBoxes[[email protected]]

"[email protected]"

I'm not sure what the practicality of this is, but this is realistically the only robust way to do it. You'd probably need to do a bunch of stylesheet customization to get any real use out of this.

Edit

I have one more suggestion. It seems like you're trying to paste into input cells, which aren't the easiest cells to work with for string processing. Instead, I suggest you paste the email addresses into a Text cell (see Interactively create a new text cell in a notebook) and evaluate the following code below the text cell:

nb = InputNotebook[];
NotebookFind[nb, "Text", Previous, CellStyle];
str = First @ NotebookRead[nb]
StringTrim @ StringSplit[str]

enter image description here

$\endgroup$
4
  • $\begingroup$ Thank you @Sjoerd Smit, your post is an elegant approach. In my case the problem initiates when simply cut / paste a delimited list of strings that contains "@" ">" ... into a Notebook input line which produces a list of expressions. Perhaps you know of a way to invoke that Mathematica produce a list of strings instead of a list of expressions? $\endgroup$
    – user96574
    Commented May 1 at 13:11
  • 1
    $\begingroup$ @user96574 Where are you copy-pasting from? If you paste a string into a notebook between two quote marks ("<paste here>"), you shouldn't have any issues. If the addresses come from a file, just Import the file instead of trying to use copy-paste. I do have one more idea though. Let me edit the answer. $\endgroup$ Commented May 1 at 13:46
  • $\begingroup$ Thank you @Sjoerd Smit that is wonderful. A little further help if you please, how do I submit that my question is thus answered? $\endgroup$
    – user96574
    Commented May 1 at 21:05
  • $\begingroup$ @user96574 There should be a checkmark button close to the up/downvote buttons on each answer. You just click the checkmark on the answer that answered your question. $\endgroup$ Commented May 2 at 8:24
0
$\begingroup$

It just so happens that your symbolic email parses to an actual Mathematica expression:

exp = username@domainname . extension;
exp // FullForm
(* Dot[username[domainname], extension] *)

This is a weird coincidence that you probably shouldn't be counting on. But, since it's a valid expression, you can easily turn it into a string and then post-process it into what you want:

StringReplace[ToString[exp], {"[" -> "@", "] . " -> "."}]
(* "[email protected]" *)

That's a pretty hacky and hard-coded transformation--you might need to generalize it if you want to handle all valid emails.

$\endgroup$
1
  • $\begingroup$ Thank you @lericr, Indeed this is the work around that I used. You're right in that it doesn't cover all the special characters that ToString would have difficulty with, one additional one is >. $\endgroup$
    – user96574
    Commented May 1 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.