diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95410ea47..4ea0eb152 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@
 - Fix a false positive for `RSpec/ExpectActual` when used with rspec-rails routing matchers. ([@naveg])
 - Add new `RSpec/RepeatedSubjectCall` cop. ([@drcapulet])
 - Add configuration option `ResponseMethods` to `RSpec/Rails/HaveHttpStatus`. ([@ydah])
+- Fix `RSpec/ExampleWording` in escaping and `%` string literals. ([@r7kamura])
 
 ## 2.26.1 (2024-01-05)
 
diff --git a/lib/rubocop/cop/rspec/example_wording.rb b/lib/rubocop/cop/rspec/example_wording.rb
index a650183f2..b31cb5c31 100644
--- a/lib/rubocop/cop/rspec/example_wording.rb
+++ b/lib/rubocop/cop/rspec/example_wording.rb
@@ -92,18 +92,27 @@ def add_wording_offense(node, message)
           add_offense(docstring, message: message) do |corrector|
             next if node.heredoc?
 
-            corrector.replace(docstring, replacement_text(node))
+            if node.str_type? && needs_escape?(node)
+              corrector.replace(node, replacement_text(node).inspect)
+            else
+              corrector.replace(docstring, replacement_text(node))
+            end
           end
         end
 
         def docstring(node)
-          expr = node.source_range
+          if node.str_type? && !node.heredoc?
+            node.source_range.with(
+              begin_pos: node.loc.begin.end_pos,
+              end_pos: node.loc.end.begin_pos
+            )
+          else
+            node.source_range.adjust(begin_pos: 1, end_pos: -1)
+          end
+        end
 
-          Parser::Source::Range.new(
-            expr.source_buffer,
-            expr.begin_pos + 1,
-            expr.end_pos - 1
-          )
+        def needs_escape?(node)
+          node.value.include?(node.loc.end.source)
         end
 
         def replacement_text(node)
diff --git a/spec/rubocop/cop/rspec/example_wording_spec.rb b/spec/rubocop/cop/rspec/example_wording_spec.rb
index 100ae719d..834ccd50b 100644
--- a/spec/rubocop/cop/rspec/example_wording_spec.rb
+++ b/spec/rubocop/cop/rspec/example_wording_spec.rb
@@ -352,4 +352,94 @@
       RUBY
     end
   end
+
+  context "when message includes `'` in `'...'`" do
+    it 'corrects message with `String#inspect`' do
+      expect_offense(<<~'RUBY')
+        it 'should return foo\'s bar' do
+            ^^^^^^^^^^^^^^^^^^^^^^^^ Do not use should when describing your tests.
+        end
+      RUBY
+
+      expect_correction(<<~RUBY)
+        it "returns foo's bar" do
+        end
+      RUBY
+    end
+  end
+
+  context 'when message includes `"` in `"..."`' do
+    it 'corrects message with `String#inspect`' do
+      expect_offense(<<~'RUBY')
+        it "should return \"foo\"" do
+            ^^^^^^^^^^^^^^^^^^^^^ Do not use should when describing your tests.
+        end
+      RUBY
+
+      expect_correction(<<~'RUBY')
+        it "returns \"foo\"" do
+        end
+      RUBY
+    end
+  end
+
+  context 'when message includes `!` in `%!...!`' do
+    it 'corrects message with `String#inspect`' do
+      expect_offense(<<~'RUBY')
+        it %!should return foo\!! do
+             ^^^^^^^^^^^^^^^^^^^ Do not use should when describing your tests.
+        end
+      RUBY
+
+      expect_correction(<<~RUBY)
+        it "returns foo!" do
+        end
+      RUBY
+    end
+  end
+
+  context 'when message includes `)` in `%q(...)`' do
+    it 'corrects message with `String#inspect`' do
+      expect_offense(<<~RUBY)
+        it %q(should return foo (bar)) do
+              ^^^^^^^^^^^^^^^^^^^^^^^ Do not use should when describing your tests.
+        end
+      RUBY
+
+      expect_correction(<<~RUBY)
+        it "returns foo (bar)" do
+        end
+      RUBY
+    end
+  end
+
+  context 'when message includes `"` in `%q(...)`' do
+    it 'corrects message with direct substring replacement' do
+      expect_offense(<<~RUBY)
+        it %q(should return "foo") do
+              ^^^^^^^^^^^^^^^^^^^ Do not use should when describing your tests.
+        end
+      RUBY
+
+      expect_correction(<<~RUBY)
+        it %q(returns "foo") do
+        end
+      RUBY
+    end
+  end
+
+  context 'when message includes `"` and `)` in `%q(...)`' do
+    it 'corrects message with `String#inspect`' do
+      expect_offense(<<~RUBY)
+        it %q(should return "foo (bar)") do
+              ^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use should when describing your tests.
+        end
+      RUBY
+
+      expect_correction(<<~'RUBY')
+        it "returns \"foo (bar)\"" do
+        end
+      RUBY
+    end
+  end
 end