class String

Practical examples and pitfalls for String

String examples: clean text and count the right thing

Practical notes by Ruby-Doc.org

Keep a useful copy of the incoming text

A support form may need a tidy display name while retaining the exact submitted value for troubleshooting. Start with operations that return new strings. In this example, strip removes surrounding whitespace and gsub replaces runs of whitespace inside the value. The original variable still refers to the submitted text.

Example 1
submitted = "  Ruby\t\tDocs  "
display_name = submitted.strip.gsub(/\s+/, " ")
p display_name
p submitted
Expected output
"Ruby Docs"
"  Ruby\t\tDocs  "

Whether internal whitespace should collapse is a product decision. It can make sense for a display label, but would change the meaning of a password or a piece of source code. Name the transformation after the field it is intended for instead of turning it into a universal text cleaner.

Separate storage length from display length

A character counter and an upload-size limit do different jobs. The example uses a letter followed by a combining accent. The text contains two characters but one grapheme cluster, which is often the more useful unit for a user-facing count. Its UTF-8 byte count is different again.

Example 2
text = "e\u0301"
p text.bytesize
p text.length
p text.each_grapheme_cluster.count
Expected output
3
2
1

Pick the unit before writing a limit. bytesize belongs with byte budgets; length counts characters according to the string's encoding; each_grapheme_cluster helps when the interface is talking about visible text units. Even grapheme count is not a measure of screen width. Font, script and layout still affect how much room a label needs.

Treat encoding and mutation as separate choices

Changing an encoding label is different from converting bytes to another encoding. force_encoding changes the label; encode performs a conversion. If imported text looks damaged, first establish the actual input encoding rather than trying labels until the output looks plausible.

Be equally explicit about ownership. Calling replace changes an existing string even though the method has no exclamation mark. Conversely, methods such as strip! can return nil when no change was necessary. Check already-clean text, empty text and non-ASCII text when testing a string-processing helper. Those cases expose different assumptions and deserve separate expected results.

API reference: String API reference

Related: Regexp · IO

A String object has an arbitrary sequence of bytes, typically representing text or binary data. A String object may be created using String::new or as literals.

String objects differ from Symbol objects in that Symbol objects are designed to be used as identifiers, instead of text or data.

You can create a String object explicitly with:

You can convert certain objects to Strings with:

Some String methods modify self. Typically, a method whose name ends with ! modifies self and returns self; often, a similarly named method (without the !) returns a new string.

In general, if both bang and non-bang versions of a method exist, the bang method mutates and the non-bang method does not. However, a method without a bang can also mutate, such as String#replace.

Substitution Methods

These methods perform substitutions:

Each of these methods takes:

The examples in this section mostly use the String#sub and String#gsub methods; the principles illustrated apply to all four substitution methods.

Argument pattern

Argument pattern is commonly a regular expression:

s = 'hello'
s.sub(/[aeiou]/, '*') # => "h*llo"
s.gsub(/[aeiou]/, '*') # => "h*ll*"
s.gsub(/[aeiou]/, '')  # => "hll"
s.sub(/ell/, 'al')     # => "halo"
s.gsub(/xyzzy/, '*')   # => "hello"
'THX1138'.gsub(/\d+/, '00') # => "THX00"

When pattern is a string, all its characters are treated as ordinary characters (not as Regexp special characters):

'THX1138'.gsub('\d+', '00') # => "THX1138"

String replacement

If replacement is a string, that string determines the replacing string that is substituted for the matched text.

Each of the examples above uses a simple string as the replacing string.

String replacement may contain back-references to the pattern’s captures:

See Regexp for details.

Note that within the string replacement, a character combination such as $& is treated as ordinary text, not as a special match variable. However, you may refer to some special match variables using these combinations:

See Regexp for details.

Note that \\ is interpreted as an escape, i.e., a single backslash.

Note also that a string literal consumes backslashes. See String Literals for details about string literals.

A back-reference is typically preceded by an additional backslash. For example, if you want to write a back-reference \& in replacement with a double-quoted string literal, you need to write "..\\&..".

If you want to write a non-back-reference string \& in replacement, you need to first escape the backslash to prevent this method from interpreting it as a back-reference, and then you need to escape the backslashes again to prevent a string literal from consuming them: "..\\\\&..".

You may want to use the block form to avoid excessive backslashes.

Hash replacement

If the argument replacement is a hash, and pattern matches one of its keys, the replacing string is the value for that key:

h = {'foo' => 'bar', 'baz' => 'bat'}
'food'.sub('foo', h) # => "bard"

Note that a symbol key does not match:

h = {foo: 'bar', baz: 'bat'}
'food'.sub('foo', h) # => "d"

Block

In the block form, the current match string is passed to the block; the block’s return value becomes the replacing string:

s = '@'
'1234'.gsub(/\d/) { |match| s.succ! } # => "ABCD"

Special match variables such as $1, $2, $`, $&, and $' are set appropriately.

Whitespace in Strings

In the class String, whitespace is defined as a contiguous sequence of characters consisting of any mixture of the following:

Whitespace is relevant for the following methods:

What’s Here

First, what’s elsewhere. Class String:

Here, class String provides methods that are useful for:

Creating a String

Freezing/Unfreezing

Querying

Counts

Substrings

Encodings

Other

Comparing

Modifying

Each of these methods modifies self.

Insertion

Substitution

Casing

Encoding

Deletion

Converting to New String

Each of these methods returns a new String based on self, often just a modified copy of self.

Extension

Encoding

Substitution

Casing

Deletion

Duplication

Converting to Non-String

Each of these methods converts the contents of self to a non-String.

Characters, Bytes, and Clusters

Splitting

Matching

Numerics

Strings and Symbols

Iterating