4
$\begingroup$

I have a large string like this:

string = {"text, 1998, TEXTDATA, text, 2007, NEXTTEXTDATA"};

Now I want to extract TEXTDATA and NEXTTEXTDATA. I tried to use StringCases and Shortestin combination with DigitCharacterlike this:

StringCases[string, Shortest[DigitCharacter .. ~~ ___ ~~ ", "]]

but this of course yields only

(* {{"1998, ", "2007, "}} *)

So either there is a way to combine DigitCharacterwith the FIRST comma (and then probably Shortestwould work) or there is a way without Shortest?

$\endgroup$
  • $\begingroup$ do you mean you want to extract the uppercase text? $\endgroup$ – Fraccalo Feb 18 at 9:32
  • $\begingroup$ Or do you want to take the text appearing after a sequence of number and comma? $\endgroup$ – Fraccalo Feb 18 at 9:38
  • $\begingroup$ @Fraccalo yes but in this example, it is just uppercase for illustrative purposes... $\endgroup$ – M.A. Feb 18 at 9:38
  • $\begingroup$ @Fraccalo the text appearing between number+ FIRST comma and SECOND comma $\endgroup$ – M.A. Feb 18 at 9:40
4
$\begingroup$
StringCases[string, DigitCharacter .. ~~ ", " ~~ w : (LetterCharacter ..) :> w]

{{"TEXTDATA", "NEXTTEXTDATA"}}

or

StringCases[string, NumberString ~~ ", " ~~ w : (LetterCharacter ..) :> w]

{{"TEXTDATA", "NEXTTEXTDATA"}}

or

StringCases[string, ", " ~~ w : (LetterCharacter ..) ~~ EndOfString | "," :> w]

{{"TEXTDATA", "NEXTTEXTDATA"}}

|improve this answer|||||
$\endgroup$
  • $\begingroup$ string has a very simple structure. What if string contains other numbers and blanks? Is there a way to implement an exact rule: just (and only just) take the text between the 4-digit (its always a year but a string) and the SECOND comma AFTER this year-digit? $\endgroup$ – M.A. Feb 18 at 10:17
  • $\begingroup$ @M.A., you can try a more specific pattern like StringCases[string, Repeated[DigitCharacter, {4}] ~~ ", " ~~ w : (LetterCharacter ..) ~~ "," | EndOfString :> w] $\endgroup$ – kglr Feb 18 at 10:40
  • $\begingroup$ This appears to work only with "TEXTDATA" (again, sorry for my oversimplified string example). What if I have "A TEXT LIKE THIS" (with blanks)? $\endgroup$ – M.A. Feb 18 at 11:48
  • 1
    $\begingroup$ StringCases[string, Repeated[DigitCharacter, {4}] ~~ ", " ~~ w : (Except[","] ..) ~~ "," | EndOfString :> w]? $\endgroup$ – kglr Feb 18 at 12:02
  • $\begingroup$ Just a minor modification: StringCases[string, ", " ~~ Repeated[DigitCharacter, {4}] ~~ ", " ~~ w : (Except[","] ..) ~~ ", " | EndOfString :> w] This ensures that Strings like "P1675" are kicked out. Thx! $\endgroup$ – M.A. Feb 18 at 12:16
3
$\begingroup$

For the moment, it seems to suffice just to understand the selection criterion as to find all the substrings consisting of upper letters. To convey that information, one can use RegularExpression or CharacterRange to construct the string pattern.

string = {"text, 1998, TEXTDATA, text, 2007, NEXTTEXTDATA"};
stringpattern1 = RegularExpression["[[:upper:]]+"];
stringpattern2 = CharacterRange["A", "Z"] ..;
StringCases[string, stringpattern1]
StringCases[string, stringpattern2]

both with the same result

{{"TEXTDATA", "NEXTTEXTDATA"}}


If one has to work by specifying the environment of the substrings rather than the information of the target substrings themselves, the string pattern is also accessible as

stringpattern3 = RegularExpression["\\d, ([^ ,]+),?"] -> "$1";

which is saying "picking out whatever parenthesized characters except a blank or a comma, following a substring consisting of a digit, a comma, and a blank, and simultaneously followed by a comma or nothing (no more than one comma)".

|improve this answer|||||
$\endgroup$
2
$\begingroup$
string = {"text, 1998, TEXTDATA, text, 2007, NEXTTEXTDATA"};
list = StringSplit[string[[1]], ", "];
filter = RotateRight[StringMatchQ[list, NumberString]];

Pick[list, filter]

{"TEXTDATA", "NEXTTEXTDATA"}

|improve this answer|||||
$\endgroup$
1
$\begingroup$
StringCases[string, 
RegularExpression["[0-9]{4},\\s([A-Z]+)"]:> "$1"]

{{TEXTDATA, NEXTTEXTDATA}}

(In Mathematica, $1 refers to the capturing group (within the parentheses)).

string2 = {"text, 1993,         TEXTDATA, text, 2007, NEXTTEXTDATA"};

StringCases[string2, 
RegularExpression["[0-9]{4},\\s+([A-Z]+)"]:> "$1"]

{{TEXTDATA, NEXTTEXTDATA}}

Edit

For " just (and only just) take the text between the 4-digit (its always a year but a string) and the SECOND comma AFTER this year-digit", maybe:

StringCases[string, 
RegularExpression[",\\s+[0-9]{4},\\s+([A-Z]+)"]:> "$1"]

{{TEXTDATA, NEXTTEXTDATA}}

Edit 2

Answering a comment by the OP:

" What if [...] "TEXT DATA" or "NEXT TEXT DATA"?

Such a case is easily handled by a RegExp by modification of the capturing group:

string3 = {"text, 1993,         TEXT DATA, text, 2007, NEXT TEXT DATA"};

StringCases[string3, 
RegularExpression["[0-9]{4},\\s+([A-Z\s]+)"]:> "$1"]

{{TEXT DATA, NEXT TEXT DATA}}

Edit 3

For a more complex string:

string4 = {"text, 1993,         TEXT-DATA, text, 2007, NEXT/TEXT (2004) DATA"};

The regex may be modified as follows (one way!):

StringCases[string4, 
RegularExpression["[0-9]{4},\\s+([A-Z0-9\s-()/]+)"]:> "$1"]

{{TEXT-DATA, NEXT/TEXT (2004) DATA}}

|improve this answer|||||
$\endgroup$
  • $\begingroup$ See also my comment to the answer of @kglr: What if I have "TEXT DATA" or "NEXT TEXT DATA"? $\endgroup$ – M.A. Feb 18 at 11:49
  • 2
    $\begingroup$ @M.A. Such a case is easily handled by regexp. See edit $\endgroup$ – user1066 Feb 18 at 12:00
  • $\begingroup$ very impressive but (for me!) the solution from kglr is more understandable... $\endgroup$ – M.A. Feb 18 at 12:25
  • $\begingroup$ Maybe. But (borrowing heavily from @Αλέξανδρος Ζεγγ) StringCases[string, RegularExpression["[0-9]{4},\\s+([^,]+),?"]:> "$1"] is very understandable to me, and seems to tersely and specifically meet all your requirements. $\endgroup$ – user1066 Feb 18 at 13:45
  • 1
    $\begingroup$ Substituting RegularExpression["[^A-Za-z][0-9]{4} ..." (four-digit number that cannot be preceded by any letter, uppercase or lowercase), RegularExpression["\\s[0-9]{4} ..." (four-digit number preceded by a single whitespace) or RegularExpression[",\\s+[0-9]{4} ..." (comma, followed an one-or-more whitespace(s), followed by four-digit number) are possible solutions to that scenario (see my answer). $\endgroup$ – user1066 Feb 18 at 14:31

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.