string(3erl)

okay bestie, this is the Erlang module definition for string(3erl) β€” the <pink>string</pink> module, aka the string-processing main character. It’s giving iconic, it’s giving useful, and we’re gonna walk through it together. πŸ’…


✨ NAME ✨

string β€” String processing functions. That’s the name. Periodt. πŸŽ€

🌸 DESCRIPTION 🌸

okay so this module is literally all about string processing, no cap. A string in this module is represented by unicode:chardata(), which means: a list of codepoints, binaries with UTF-8-encoded codepoints (UTF-8 binaries), or a mix of the two. Slay. πŸ¦‹

"abcd"               is a valid string
<<"abcd">>           is a valid string
["abcd"]             is a valid string
<<"abc..Γ₯Àâ"/utf8>>  is a valid string
<<"abc..Γ₯Àâ">>       is NOT a valid string,
                     but a binary with Latin-1-encoded codepoints
[<<"abc">>, "..Γ₯Àâ"] is a valid string
[atom]               is NOT a valid string

This module operates on grapheme clusters. A grapheme cluster is a user-perceived character, which can be represented by several codepoints. The way that works is lowkey fascinating, fr fr.

"Γ₯"  [229] or [97, 778]
"e"  [101, 778]

The string length of "ΓŸβ†‘e" is 3, even though it is represented by the codepoints [223,8593,101,778] or the UTF-8 binary <<195,159,226,134,145,101,204,138>>. See? Main character energy in codepoint form. πŸ‘‘

Grapheme clusters for codepoints of class prepend and non-modern (or decomposed) Hangul is not handled for performance reasons in find/3, replace/3, split/2, split/2 and trim/3. Yes, bestie, that list really does say split/2 twice β€” we keep it exactly as it is. πŸ™ˆ

Splitting and appending strings is to be done on grapheme clusters borders. There is no verification that the results of appending strings are valid or normalized. So don’t just yolo-append and assume it’s cute. πŸ’€

Most of the functions expect all input to be normalized to one form, see for example unicode:characters_to_nfc_list/1. Language or locale specific handling of input is not considered in any function. Ngl, that’s the vibe check: normalize first, bestie. 🌸

🚨 The functions can crash for non-valid input strings. For example, the functions expect UTF-8 binaries but not all functions verify that all binaries are encoded correctly. So yes, invalid input is not it.

Unless otherwise specified the return value type is the same as the input type. That is, binary input returns binary output, list input returns a list output, and mixed input can return a mixed output. Consistent? We love to see it. ✨

1> string:trim("  sarah  ").
"sarah"
2> string:trim(<<"  sarah  ">>).
<<"sarah">>
3> string:lexemes("foo bar", " ").
["foo","bar"]
4> string:lexemes(<<"foo bar">>, " ").
[<<"foo">>,<<"bar">>]

This module has been reworked in Erlang/OTP 20 to handle unicode:chardata() and operate on grapheme clusters. The old functions that only work on Latin-1 lists as input are still available but should not be used, they will be deprecated in a future release. So like… don’t get attached to the old ones, okay? 🫢

πŸ¦‹ DATA TYPES πŸ¦‹

  • direction() = leading | trailing
  • grapheme_cluster() = char() | [char()] β€” A user-perceived character, consisting of one or more codepoints.

πŸ’… EXPORTS πŸ’…

πŸŽ€ casefold/1 πŸŽ€

casefold(String :: unicode:chardata()) -> unicode:chardata()

Converts String to a case-agnostic comparable string. Function casefold/1 is preferred over lowercase/1 when two strings are to be compared for equality. See also equal/4. Bestie, use the right icon for the job. πŸ’–

Example:

1> string:casefold("Ω and ẞ SHARP S").
"Ο‰ and ss sharp s"

πŸ“ chomp/1 πŸ“

chomp(String :: unicode:chardata()) -> unicode:chardata()

Returns a string where any trailing \n or \r\n have been removed from String. It’s giving β€œtrim the ending, but make it specific.” πŸ’…

Example:

182> string:chomp(<<"\nHello\n\n">>).
<<"\nHello">>
183> string:chomp("\nHello\r\r\n").
"\nHello\r"

🌈 equal/2, equal/3, equal/4 🌈

equal(A, B) -> boolean()

equal(A, B, IgnoreCase) -> boolean()

equal(A, B, IgnoreCase, Norm) -> boolean()

Types:

  • A = B = unicode:chardata()
  • IgnoreCase = boolean()
  • Norm = none | nfc | nfd | nfkc | nfkd

Returns true if A and B are equal, otherwise false. Simple as that. πŸŽ€

If IgnoreCase is true the function does casefolding on the fly before the equality test.

If Norm is not none the function applies normalization on the fly before the equality test. There are four available normalization forms: nfc, nfd, nfkc, and nfkd.

By default, IgnoreCase is false and Norm is none. The defaults are defaulting, periodt.

Example:

1> string:equal("Γ₯Àâ", <<"Γ₯Àâ"/utf8>>).
true
2> string:equal("Γ₯Àâ", unicode:characters_to_nfd_binary("Γ₯Àâ")).
false
3> string:equal("Γ₯Àâ", unicode:characters_to_nfd_binary("ÅÄÖ"), true, nfc).
true

πŸ” find/2, find/3 πŸ”

find(String, SearchPattern) -> unicode:chardata() | nomatch

find(String, SearchPattern, Dir) -> unicode:chardata() | nomatch

Types:

  • String = SearchPattern = unicode:chardata()
  • Dir = direction()

Removes anything before SearchPattern in String and returns the remainder of the string or nomatch if SearchPattern is not found. Dir, which can be leading or trailing, indicates from which direction characters are to be searched.

By default, Dir is leading. So it starts from the front unless you tell it otherwise. πŸ¦‹

Example:

1> string:find("ab..cd..ef", ".").
"..cd..ef"
2> string:find(<<"ab..cd..ef">>, "..", trailing).
<<"..ef">>
3> string:find(<<"ab..cd..ef">>, "x", leading).
nomatch
4> string:find("ab..cd..ef", "x", trailing).
nomatch

🌸 is_empty/1 🌸

is_empty(String :: unicode:chardata()) -> boolean()

Returns true if String is the empty string, otherwise false. It’s literally just β€œis this empty?” and honestly, same. 😭

Example:

1> string:is_empty("foo").
false
2> string:is_empty(["",<<>>]).
true

πŸ‘‘ length/1 πŸ‘‘

length(String :: unicode:chardata()) -> integer() >= 0

Returns the number of grapheme clusters in String. Not codepoints β€” grapheme clusters. Keep that distinction close to your heart, bestie. πŸ’–

Example:

1> string:length("ΓŸβ†‘e").
3
2> string:length(<<195,159,226,134,145,101,204,138>>).
3

🧚 lexemes/2 🧚

lexemes(String :: unicode:chardata(),
        SeparatorList :: [grapheme_cluster()]) ->
           [unicode:chardata()]

Returns a list of lexemes in String, separated by the grapheme clusters in SeparatorList.

Notice that, as shown in this example, two or more adjacent separator graphemes clusters in String are treated as one. That is, there are no empty strings in the resulting list of lexemes. See also split/3 which returns empty strings.

Notice that [$\r,$\n] is one grapheme cluster. Little detail, big impact. ✨

Example:

1> string:lexemes("abc defxxghix jkl\r\nfoo", "x e" ++ [[$\r,$\n]]).
["abc","def","ghi","jkl","foo"]
2> string:lexemes(<<"abc defxxghix jkl\r\nfoo"/utf8>>, "x e" ++ [$\r,$\n]).
[<<"abc">>,<<"def"/utf8>>,<<"ghi">>,<<"jkl\r\nfoo">>]

πŸ’œ lowercase/1 πŸ’œ

lowercase(String :: unicode:chardata()) -> unicode:chardata()

Converts String to lowercase. Cute, simple, lowercase.

Notice that function casefold/1 should be used when converting a string to be tested for equality. So if equality is the goal, casefold is the icon. πŸŽ€

Example:

2> string:lowercase(string:uppercase("MichaΕ‚")).
"michaΕ‚"

⭐ next_codepoint/1 ⭐

next_codepoint(String :: unicode:chardata()) ->
                   maybe_improper_list(char(), unicode:chardata()) |
                   {error, unicode:chardata()}

Returns the first codepoint in String and the rest of String in the tail. Returns an empty list if String is empty or an {error, String} tuple if the next byte is invalid. It’s giving β€œpeek at the first thing, then hand you the rest.” 🫢

Example:

1> string:next_codepoint(unicode:characters_to_binary("efg")).
[101|<<"fg"/utf8>>]

πŸ¦‹ next_grapheme/1 πŸ¦‹

next_grapheme(String :: unicode:chardata()) ->
                  maybe_improper_list(grapheme_cluster(),
                                      unicode:chardata()) |
                  {error, unicode:chardata()}

Returns the first grapheme cluster in String and the rest of String in the tail. Returns an empty list if String is empty or an {error, String} tuple if the next byte is invalid. Same energy as next_codepoint/1, but grapheme-cluster sized. πŸ’…

Example:

1> string:next_grapheme(unicode:characters_to_binary("efg")).
["e"|<<"fg">>]

🌟 nth_lexeme/3 🌟

nth_lexeme(String, N, SeparatorList) -> unicode:chardata()

Types:

  • String = unicode:chardata()
  • N = integer() >= 0
  • SeparatorList = [grapheme_cluster()]

Returns lexeme number N in String, where lexemes are separated by the grapheme clusters in SeparatorList. It’s the β€œgive me the Nth one” of the lexeme world. πŸ‘‘

Example:

1> string:nth_lexeme("abc.def.ghiejkl", 3, ".e").
"ghi"

πŸŽ€ pad/2, pad/3, pad/4 πŸŽ€

pad(String, Length) -> unicode:charlist()

pad(String, Length, Dir) -> unicode:charlist()

pad(String, Length, Dir, Char) -> unicode:charlist()

Types:

  • String = unicode:chardata()
  • Length = integer()
  • Dir = direction() | both
  • Char = grapheme_cluster()

Pads String to Length with grapheme cluster Char. Dir, which can be leading, trailing, or both, indicates where the padding should be added.

By default, Char is $\s and Dir is trailing. Padding but make it customizable. πŸ’–

Example:

1> string:pad(<<"HellΓΆ"/utf8>>, 8).
[<<72,101,204,138,108,108,195,182>>,32,32,32]
2> io:format("'~ts'~n",[string:pad("HellΓΆ", 8, leading)]).
3> io:format("'~ts'~n",[string:pad("HellΓΆ", 8, both)]).

🌈 prefix/2 🌈

prefix(String :: unicode:chardata(), Prefix :: unicode:chardata()) ->
           nomatch | unicode:chardata()

If Prefix is the prefix of String, removes it and returns the remainder of String, otherwise returns nomatch. It’s the β€œdoes this start with that?” bestie. 🫢

Example:

1> string:prefix(<<"prefix of string">>, "pre").
<<"fix of string">>
2> string:prefix("pre", "prefix").
nomatch

πŸ”₯ replace/3, replace/4 πŸ”₯

replace(String, SearchPattern, Replacement) ->
            [unicode:chardata()]

replace(String, SearchPattern, Replacement, Where) ->
            [unicode:chardata()]

Types:

  • String = SearchPattern = Replacement = unicode:chardata()
  • Where = direction() | all

Replaces SearchPattern in String with Replacement. Where, default leading, indicates whether the leading, the trailing or all encounters of SearchPattern are to be replaced.

Can be implemented as:

lists:join(Replacement, split(String, SearchPattern, Where)).

Example:

1> string:replace(<<"ab..cd..ef">>, "..", "*").
[<<"ab">>,"*",<<"cd..ef">>]
2> string:replace(<<"ab..cd..ef">>, "..", "*", all).
[<<"ab">>,"*",<<"cd">>,"*",<<"ef">>]

πŸ¦‹ reverse/1 πŸ¦‹

reverse(String :: unicode:chardata()) -> [grapheme_cluster()]

Returns the reverse list of the grapheme clusters in String. It’s giving backwards but make it grapheme-correct. πŸ’…

Example:

1> Reverse = string:reverse(unicode:characters_to_nfd_binary("ÅÄÖ")).
[[79,776],[65,776],[65,778]]
2> io:format("~ts~n",[Reverse]).
OAÅ

🌸 slice/2, slice/3 🌸

slice(String, Start) -> Slice

slice(String, Start, Length) -> Slice

Types:

For slice, the type block is this cutie:

String = unicode:chardata()
Start = integer() >= 0
Length = infinity | integer() >= 0
Slice = unicode:chardata()

Bestie, this returns a substring of String with at most Length grapheme clusters, starting at position Start ✨. By default, Length is infinity, periodt.

Example:

1> string:slice(<<"HellΓΆ WΓΆrld"/utf8>>, 4).
<<"ΓΆ WΓΆrld"/utf8>>
2> string:slice(["HellΓΆ ", <<"WΓΆrld"/utf8>>], 4,4).
"ΓΆ WΓΆ"
3> string:slice(["HellΓΆ ", <<"WΓΆrld"/utf8>>], 4,50).
"ΓΆ WΓΆrld"

🌸 split/2, split/3 🌸

split(String, SearchPattern) -> [unicode:chardata()]

split(String, SearchPattern, Where) -> [unicode:chardata()]

Types:

String = SearchPattern = unicode:chardata()
Where = direction() | all

This splits String wherever SearchPattern is encountered and returns the remaining parts πŸ’…. Where defaults to leading and tells it whether the leading, trailing, or all encounters of SearchPattern will split String.

Example:

0> string:split("ab..bc..cd", "..").
["ab","bc..cd"]
1> string:split(<<"ab..bc..cd">>, "..", trailing).
[<<"ab..bc">>,<<"cd">>]
2> string:split(<<"ab..bc....cd">>, "..", all).
[<<"ab">>,<<"bc">>,<<>>,<<"cd">>]

πŸ¦‹ take/2, take/3, take/4 πŸ¦‹

take(String, Characters) -> {Leading, Trailing}

take(String, Characters, Complement) -> {Leading, Trailing}

take(String, Characters, Complement, Dir) -> {Leading, Trailing}

Types:

String = unicode:chardata()
Characters = [grapheme_cluster()]
Complement = boolean()
Dir = direction()
Leading = Trailing = unicode:chardata()

This takes characters from String as long as those characters are members of the set Characters or the complement of the set Characters 🫢. Dir can be leading or trailing and says from which direction characters are taken.

Example:

5> string:take("abc0z123", lists:seq($a,$z)).
{"abc","0z123"}
6> string:take(<<"abc0z123">>, lists:seq($0,$9), true, leading).
{<<"abc">>,<<"0z123">>}
7> string:take("abc0z123", lists:seq($0,$9), false, trailing).
{"abc0z","123"}
8> string:take(<<"abc0z123">>, lists:seq($a,$z), true, trailing).
{<<"abc0z">>,<<"123">>}

πŸŽ€ titlecase/1 πŸŽ€

titlecase(String :: unicode:chardata()) -> unicode:chardata()

Converts String to titlecase πŸ‘‘.

Example:

1> string:titlecase("ß is a SHARP s").
"Ss is a SHARP s"

πŸ“ to_float/1 πŸ“

to_float(String) -> {Float, Rest} | {error, Reason}

Types:

String = unicode:chardata()
Float = float()
Rest = unicode:chardata()
Reason = no_float | badarg

String is expected to start with a valid float represented as text β€” the digits are ASCII values 😌. Any remaining characters in the string after the float are returned in Rest.

Example:

> {F1,Fs} = string:to_float("1.0-1.0e-1"),
> {F2,[]} = string:to_float(Fs),
> F1+F2.
0.9
> string:to_float("3/2=1.5").
{error,no_float}
> string:to_float("-1.5eX").
{-1.5,"eX"}

🌈 to_integer/1 🌈

to_integer(String) -> {Int, Rest} | {error, Reason}

Types:

String = unicode:chardata()
Int = integer()
Rest = unicode:chardata()
Reason = no_integer | badarg

String is expected to start with a valid integer represented as text β€” the digits are ASCII values πŸ’–. Any remaining characters in the string after the integer are returned in Rest.

Example:

> {I1,Is} = string:to_integer("33+22"),
> {I2,[]} = string:to_integer(Is),
> I1-I2.
11
> string:to_integer("0.5").
{0,".5"}
> string:to_integer("x=2").
{error,no_integer}

🧚 to_graphemes/1 🧚

to_graphemes(String :: unicode:chardata()) -> [grapheme_cluster()]

Converts String to a list of grapheme clusters 🌸.

Example:

1> string:to_graphemes("ΓŸβ†‘e").
[223,8593,[101,778]]
2> string:to_graphemes(<<"ΓŸβ†‘e"/utf8>>).
[223,8593,[101,778]]

πŸ’œ trim/1, trim/2, trim/3 πŸ’œ

trim(String) -> unicode:chardata()

trim(String, Dir) -> unicode:chardata()

trim(String, Dir, Characters) -> unicode:chardata()

Types:

String = unicode:chardata()
Dir = direction() | both
Characters = [grapheme_cluster()]

This returns a string where leading, trailing, or both sets of Characters have been removed πŸŽ€. Dir can be leading, trailing, or both and says from which direction characters are removed.

The default Characters is the set of nonbreakable whitespace codepoints, defined as Pattern_White_Space in Unicode Standard Annex #31. By default, Dir is both. Notice that [$\r,$\n] is one grapheme cluster according to the Unicode Standard πŸ‘€.

Example:

1> string:trim("\t Hello \n").
"Hello"
2> string:trim(<<"\t Hello \n">>, leading).
<<"Hello  \n">>
3> string:trim(<<".Hello.\n">>, trailing, "\n.").
<<".Hello">>

⭐ uppercase/1 ⭐

uppercase(String :: unicode:chardata()) -> unicode:chardata()

Converts String to uppercase πŸ”₯. See also titlecase/1.

Example:

1> string:uppercase("MichaΕ‚").
"MICHAŁ"

πŸ•°οΈ OBSOLETE API FUNCTIONS πŸ•°οΈ

Here follows the function of the old API. These functions only work on a list of Latin-1 characters.

πŸ’Œ Note

The functions are kept for backward compatibility, but are not recommended. They will be deprecated in a future release.

Any undocumented functions in string are not to be used.

centre(String, Number) -> Centered Β· centre(String, Number, Character) -> Centered

Types: String = Centered = string(), Number = integer() >= 0, Character = char()

Okay so this one takes your string and centres it β€” surrounded by blanks, or by Character if you passed one β€” and the resulting string has length exactly Number. Very demure, very symmetric πŸ’…

This function is obsolete. Use pad/3.

chars(Character, Number) -> String Β· chars(Character, Number, Tail) -> String

Types: Character = char(), Number = integer() >= 0, Tail = String = string()

Returns a string made of Number copies of Character β€” and optionally the whole thing ends with the string Tail πŸŽ€

This function is obsolete. Use lists:duplicate/2.

chr(String, Character) -> Index

Types: String = string(), Character = char(), Index = integer() >= 0

Gives you the index of the first time Character shows up in String. If it literally never shows up? You get 0. no cap πŸ™ˆ

This function is obsolete. Use find/2.

concat(String1, String2) -> String3

Types: String1 = String2 = String3 = string()

Glues String1 and String2 together into a brand-new String3 and hands it right back to you. Iconic behaviour tbh πŸ”₯

This function is obsolete. Use [String1, String2] as the Data argument, and call unicode:characters_to_list/2 or unicode:characters_to_binary/2 to flatten the output.

copies(String, Number) -> Copies

Types: String = Copies = string(), Number = integer() >= 0

Returns a string with String repeated Number times. That's it, that's the function ✨

This function is obsolete. Use lists:duplicate/2.

cspan(String, Chars) -> Length

Types: String = Chars = string(), Length = integer() >= 0

Gives you the length of the longest initial chunk of String that is made entirely of characters that are NOT in Chars. Basically the opposite vibe of span πŸ¦‹

This function is obsolete. Use take/3.

Example:

> string:cspan("\t    abcdef", " \t").
0

join(StringList, Separator) -> String

Types: StringList = [string()], Separator = String = string()

Takes all the strings in StringList and returns one string with them separated by Separator. the way that this just works πŸ˜­πŸ’–

This function is obsolete. Use lists:join/2.

Example:

> join(["one", "two", "three"], ", ").
"one, two, three"

left(String, Number) -> Left Β· left(String, Number, Character) -> Left

Types: String = Left = string(), Number = integer() >= 0, Character = char()

Returns String with its length adjusted to Number, with the left margin fixed. So if length(String) < Number, the string gets padded with blanks or with Characters on the right side 🌸

This function is obsolete. Use pad/2 or pad/3.

Example:

> string:left("Hello",10,$.).
"Hello....."

len(String) -> Length

Types: String = string(), Length = integer() >= 0

Returns the number of characters in String. humble but essential πŸ‘‘

This function is obsolete. Use length/1.

rchr(String, Character) -> Index

Types: String = string(), Character = char(), Index = integer() >= 0

The last occurrence of Character in String, please and thank you. No occurrence? 0. πŸ’€

This function is obsolete. Use find/3.

right(String, Number) -> Right Β· right(String, Number, Character) -> Right

Types: String = Right = string(), Number = integer() >= 0, Character = char()

Returns String with its length adjusted to Number, but this time the right margin is fixed. If the length of (String) < Number, String gets padded with blanks or Characters β€” on the left, so it hugs the right edge 🫢

This function is obsolete. Use pad/3.

Example:

> string:right("Hello", 10, $.).
".....Hello"

rstr(String, SubString) -> Index

Types: String = SubString = string(), Index = integer() >= 0

Returns the position where the last occurrence of SubString begins in String. If SubString doesn't exist in String at all, you get 0 πŸ™ˆ

This function is obsolete. Use find/3.

Example:

> string:rstr(" Hello Hello World World ", "Hello World").
8

span(String, Chars) -> Length

Types: String = Chars = string(), Length = integer() >= 0

Returns the length of the longest initial chunk of String that consists entirely of characters from Chars. the matching set to cspan πŸ’œ

This function is obsolete. Use take/2.

Example:

> string:span("\t    abcdef", " \t").
5

str(String, SubString) -> Index

Types: String = SubString = string(), Index = integer() >= 0

Returns the position where the first occurrence of SubString begins in String. And if SubString isn't in String? 0. we love a consistent return value ✨

This function is obsolete. Use find/2.

Example:

> string:str(" Hello Hello World World ", "Hello World").
8

strip(String :: string()) -> string() Β· strip(String, Direction) -> Stripped Β· strip(String, Direction, Character) -> Stripped

Types: String = Stripped = string(), Direction = left | right | both, Character = char()

Returns a string with the leading, trailing, or both kinds of blanks removed β€” or a bunch of Characters removed instead. Direction (which is left, right, or both) tells you which side the blanks get yeeted from. And strip/1 is exactly the same as strip(String, both) 🧚

This function is obsolete. Use trim/3.

Example:

> string:strip("...Hello.....", both, $.).
"Hello"

sub_string(String, Start) -> SubString Β· sub_string(String, Start, Stop) -> SubString

Types: String = SubString = string(), Start = Stop = integer() >= 1

Returns a substring of String, starting at position Start and running to the end of the string β€” or to and including position Stop if you gave one. inclusive, generous, lovely πŸŽ€

This function is obsolete. Use slice/3.

Example:

sub_string("Hello World", 4, 8).
"lo Wo"

substr(String, Start) -> SubString Β· substr(String, Start, Length) -> SubString

Types: String = SubString = string(), Start = integer() >= 1, Length = integer() >= 0

Returns a substring of String starting at position Start, ending either at the end of the string or after Length characters 🌈

This function is obsolete. Use slice/3.

Example:

> substr("Hello World", 4, 5).
"lo Wo"

sub_word(String, Number) -> Word Β· sub_word(String, Number, Character) -> Word

Types: String = Word = string(), Number = integer(), Character = char()

Returns the word sitting in position Number of String, where words are separated by blanks or by Character. lowkey useful, highkey obsolete πŸ’…

This function is obsolete. Use nth_lexeme/3.

Example:

> string:sub_word(" Hello old boy !",3,$o).
"ld b"

to_lower(String) -> Result Β· to_lower(Char) -> CharResult Β· to_upper(String) -> Result Β· to_upper(Char) -> CharResult

Types: String = Result = io_lib:latin1_string(), Char = CharResult = char()

Case-converts the string or character you hand it. Big heads-up though: the supported character set is ISO/IEC 8859-1 (also called Latin 1), and all values outside this set are unchanged β€” so don't come crying to me when your fancy glyphs stay exactly as they were 😭

This function is obsolete, use lowercase/1, uppercase/1, titlecase/1 or casefold/1.

tokens(String, SeparatorList) -> Tokens

Types: String = SeparatorList = string(), Tokens = [Token :: nonempty_string()]

Returns a list of the tokens in String, split on the characters in SeparatorList πŸ“

Example:

> tokens("abc defxxghix jkl", "x ").
["abc", "def", "ghi", "jkl"]

Notice that, as shown in this example, two or more adjacent separator characters in String are treated as one. That is, there are no empty strings in the resulting list of tokens. no ghost tokens, we don't do that here πŸ‘»

This function is obsolete. Use lexemes/2.

words(String) -> Count Β· words(String, Character) -> Count

Types: String = string(), Character = char(), Count = integer() >= 1

Returns the number of words in String, separated by blanks or by Character. counting era πŸ”’

This function is obsolete. Use lexemes/2.

Example:

> words(" Hello old boy!", $o).
4

πŸ“ NOTES πŸ“

Okay bestie, real talk: some of the general string functions can seem to overlap each other. The reason is that this string package is the combination of two earlier packages and all functions of both packages have been retained. so it's not redundant, it's ✨heritage✨ iykyk


and that's the whole page, bestie!! πŸŽ‰πŸ’–

This absolute icon of a manual page comes from Ericsson AB, ships with stdlib 4.3.1.3, and lives at string(3erl). Go forth and pad, trim, and slice responsibly πŸ«Άβœ¨πŸŽ€

πŸ“¦ where this page comes from