5
$\begingroup$

For example, I have a string "ahfiehfke$jfwfjejf0". Is there an elegant way to drop all characters after "$"? I know loop through and StringDrop till we hit the "$" would work, but I'm wondering if there is a better way.

$\endgroup$
  • 7
    $\begingroup$ First@StringSplit["ahfiehfke$jfw$fje$jf0", "$", 2] $\endgroup$ – Dr. belisarius Apr 28 '15 at 16:09
  • $\begingroup$ @belisarius beat me to it. $\endgroup$ – rcollyer Apr 28 '15 at 16:10
  • 2
    $\begingroup$ First[StringCases["ahfiehfke$jfwfjejf0", ___ ~~ "$", 1]] $\endgroup$ – Coolwater Apr 28 '15 at 16:11
  • 1
    $\begingroup$ @Coolwater Your version fails when there are more than one $ in the string. The correct version: First[StringCases[str, Shortest[___] ~~ "$", 1]]. $\endgroup$ – Alexey Popkov May 23 '15 at 6:08
10
$\begingroup$
StringTrim["ahfiehfke$jfwfjejf0", "$" ~~ __];

StringDelete["ahfiehfke$jfwfjejf0", "$" ~~ __]; (*V10.1*)
$\endgroup$
2
$\begingroup$

A bunch of regex methods:

str = "ahfiehfke$jfwfjejf0";

(* Coolwater *)
StringCases[str, RegularExpression["(?s).+?\\$", 1]][[1]]

StringReplace[str, RegularExpression["(?s)\\$.*"] :> "$", 1]

These use look-behind regexes:

StringReplace[str, RegularExpression["(?s)(?<=\\$).+"] :> "", 1]

StringTrim[str, RegularExpression["(?<=\\$).+"]]

(Thanks to Alexey for pointing out the need to properly handle newline characters.)

$\endgroup$
  • $\begingroup$ Note that both StringReplace solutions fail if the string contains a newline character \n after "$". You need to add the (?s) option to fix this. $\endgroup$ – Alexey Popkov May 23 '15 at 2:43
  • $\begingroup$ Ah, of course. Thanks @Alexey. $\endgroup$ – J. M. will be back soon May 23 '15 at 2:53
  • 1
    $\begingroup$ ... and the StringCases version fails if the string contains a newline character before $: it also needs the (?s) modifier. Only the StringTrim version works correctly without it because for StringTrim this modifier is already switched on internally. $\endgroup$ – Alexey Popkov May 23 '15 at 5:53
  • 1
    $\begingroup$ The StringCases version also works incorrectly when there are more than one $ in the string. The correct version: StringCases[str, RegularExpression["(?s).+?\\$"], 1][[1]]. $\endgroup$ – Alexey Popkov May 23 '15 at 6:03
  • $\begingroup$ Ah, that's what I get for trying to answer without a computer. :D Thanks again, @Alexey. $\endgroup$ – J. M. will be back soon May 23 '15 at 6:04
1
$\begingroup$

Another method:

StringTake[str, StringPosition[str, "$", 1][[1, 1]]]

A comparison of performance of different methods which give identical results:

Needs["GeneralUtilities`"]
str = StringJoin@{Table["a", {1000}], Table["ahfieh\nfke$jfw\nfje$jf0", {1000}]};
Replace[Hold[{
     StringTrim[str, "$" ~~ __] <> "$",
     StringDelete[str, "$" ~~ __] <> "$",
     First@StringSplit[str, "$", 2] <> "$",
     First[StringCases[str, Shortest[___] ~~ "$", 1]],
 StringCases[str, RegularExpression["(?s).+?\\$"], 1][[1]],
     StringReplace[str, RegularExpression["(?s)\\$.*"] :> "$", 1],
     StringReplace[str, RegularExpression["(?s)(?<=\\$).+"] :> "", 1],
 StringTrim[str, RegularExpression["(?<=\\$).+"]],
     StringTake[str, StringPosition[str, "$", 1][[1, 1]]]
     }], x_ :> {HoldForm@x, AccurateTiming@x}, {2}] // 
  ReleaseHold // TableForm

table

It seems that the absolute winner is:

StringReplace[str, RegularExpression["(?s)\\$.*"] :> "$", 1]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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