Skip to content

Alle Vorkommen in einer Zeichenkette ersetzen snippet

Jedes Vorkommen einer Teilzeichenkette gegen eine andere tauschen.

Jedes Vorkommen einer Teilzeichenkette gegen eine andere tauschen. Die Defaults sind sprachübergreifend haarsträubend uneinheitlich: JavaScripts replace() stoppt nach dem ersten Treffer (der meistgeklonte Bug des Internets), während Python, PHP, C#, Go, Rust, Swift und sogar Javas replace() den ganzen String bearbeiten, sofern keine Obergrenze übergeben wird. Die Literal-APIs bevorzugen, wenn die Needle vom Nutzer kommt — Regex-Engines interpretieren ?, * und (, sofern nicht escaped wird (Pattern.quote, Regexp.escape, re.escape), und Java und JavaScript expandieren $1 in der Ersetzung selbst bei literalen Needles. SQL versteckt die hinterhältigste Falle: Postgres replace() ist global, aber regexp_replace fixt nur den ersten Treffer, sofern nicht das Flag 'g' übergeben wird.

Runnable recipe · 15 languages
Text & Parsingstringsreplacesubstringregextext

Every language

15 languages, copy-ready. One at a time with syntax highlighting, or all inline.

SQLSQLrunnable
-- PostgreSQL
SELECT replace('cat catalog concatenate', 'cat', 'dog'); -- dog dogalog condogenate — all occurrences

SELECT regexp_replace('a-b--c', '-', '+', 'g'); -- a+b++c — without 'g' you get a+b--c

Postgres dialect. replace() is literal and global. regexp_replace is the inverse trap: it fixes ONLY the first match unless you pass the 'g' flag — a silent half-done migration if you assume replace() semantics. UPDATE table SET col = replace(col, 'old', 'new') is the classic bulk-rename idiom.

Run in the SQL playground →
JSJavaScript
const out = 'cat catalog concatenate'.replaceAll('cat', 'dog');
console.log(out); // dog dogalog condogenate

replace('cat', 'dog') with a string needle silently fixes only the FIRST match — replaceAll (ES2021) or a /g regex is the fix. replaceAll throws on a regex without the g flag. The replacement is not verbatim either: $& and $1 are expanded even for literal needles — write $$ for a literal dollar.

TSTypeScript
function replaceAll(haystack: string, needle: string, replacement: string): string {
  return haystack.split(needle).join(replacement);
}

console.log(replaceAll('cat catalog concatenate', 'cat', 'dog')); // dog dogalog condogenate

split(needle).join(replacement) is the pre-ES2021 idiom that still downlevels to old targets: every occurrence, no regex semantics, no missing-g-flag trap. Edge case: an empty needle splits per character, so guard needle !== '' at the boundary if the input is untrusted.

GoGo
package main

import (
	"fmt"
	"strings"
)

func main() {
	out := strings.ReplaceAll("cat catalog concatenate", "cat", "dog")
	fmt.Println(out) // dog dogalog condogenate
}

strings.ReplaceAll is literal and unbounded; strings.Replace takes a fourth n argument when you want a cap (n = 1 is first-only). For patterns use regexp.MustCompile(...).ReplaceAllString, and wrap user-supplied needles in regexp.QuoteMeta so a stray '*' cannot blow up the compile.

RsRust
fn main() {
    let day = "2026-08-27".replace('-', '/');
    println!("{day}"); // 2026/08/27
}

str::replace replaces every occurrence and takes a &str or char pattern; replacen(pat, replacement, n) caps the count. The stdlib is literal-only — patterns need the regex crate, where Regex::replace_all uses ${1} (not $1) for capture groups in the replacement.

PHPPHP
<?php
$out = str_replace('cat', 'dog', 'cat catalog concatenate', $count);
echo $out, PHP_EOL;   // dog dogalog condogenate
echo $count, PHP_EOL;  // 3

str_replace is already global and literal — the reverse of JavaScript's trap — and its optional fourth argument reports the match count. str_ireplace is the case-insensitive sibling; arrays let you translate many needles in one pass. preg_replace is the pattern version and interpolates $1 and \1 in the replacement.

PyPython
out = "cat catalog concatenate".replace("cat", "dog")
print(out)  # dog dogalog condogenate
print("a-b-c".replace("-", "+", 1))  # a+b-c — count caps it

str.replace replaces ALL by default; the optional count argument is how you do less. It is literal, so no escaping worries — the regex sibling re.sub needs re.escape on user needles and uses backslash group refs in the replacement.

CC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Return a malloc'd copy of src with every occurrence of from replaced by to.
   Caller frees. Empty `from` returns a plain copy (searching for it would loop). */
char *replace_all(const char *src, const char *from, const char *to) {
    size_t from_len = strlen(from), to_len = strlen(to);
    if (from_len == 0) {
        char *copy = malloc(strlen(src) + 1);
        if (copy) strcpy(copy, src);
        return copy;
    }

    size_t count = 0;
    for (const char *p = strstr(src, from); p; p = strstr(p + from_len, from))
        count++;

    char *out = malloc(strlen(src) + 1 + count * to_len); /* safe upper bound */
    if (!out) return NULL;

    char *dst = out;
    const char *cur = src, *p;
    while ((p = strstr(cur, from)) != NULL) {
        memcpy(dst, cur, (size_t)(p - cur));
        dst += p - cur;
        memcpy(dst, to, to_len);
        dst += to_len;
        cur = p + from_len;
    }
    strcpy(dst, cur); /* trailing tail */
    return out;
}

int main(void) {
    char *out = replace_all("cat catalog concatenate", "cat", "dog");
    if (out) {
        puts(out); /* dog dogalog condogenate */
        free(out);
    }
    return 0;
}

No stdlib replace — the recipe is: count non-overlapping occurrences with strstr, malloc strlen + count * (to_len - from_len) (the +1 + count * to_len form avoids underflow when the replacement shrinks), then copy segment / replacement pairs and the tail. strstr is byte-based and skips nothing implicitly; empty `from` must be special-cased or strstr never advances.

C++C++
#include <iostream>
#include <string>

std::string replace_all(std::string s, const std::string& from, const std::string& to) {
    if (from.empty()) return s;
    size_t pos = 0;
    while ((pos = s.find(from, pos)) != std::string::npos) {
        s.replace(pos, from.size(), to);
        pos += to.size(); /* skip past the fresh text or self-overlaps loop forever */
    }
    return s;
}

int main() {
    std::cout << replace_all("cat catalog concatenate", "cat", "dog") << '\n'; // dog dogalog condogenate
}

std::string::replace swaps a [pos, len) range — it does not search, so it is always paired with find in a loop. Advancing pos past the inserted replacement is load-bearing: replacing "a" with "aa" would match its own output and spin forever. std::regex_replace is the pattern sibling and replaces all matches by default.

C#C#
string result = "cat catalog concatenate".Replace("cat", "dog");
Console.WriteLine(result); // dog dogalog condogenate

String.Replace replaces every occurrence and is literal — there is no first-only overload; reach for Regex.Replace (System.Text.RegularExpressions) for patterns, or IndexOf + Remove + Insert when you need exactly one swap. Regex.Replace is global by default; its count limit is an optional parameter, the opposite of JavaScript's default.

JvJava
public class ReplaceAllOccurrences {
    public static void main(String[] args) {
        String result = "cat catalog concatenate".replace("cat", "dog");
        System.out.println(result); // dog dogalog condogenate
    }
}

Three methods, three modes: replace(CharSequence, CharSequence) is ALL occurrences and literal (contrary to JS-fueled instinct); replaceAll(regex, repl) is ALL and regex; replaceFirst is one-and-done regex. In the regex variants, escape the needle with Pattern.quote and the replacement with Matcher.quoteReplacement — a raw $ or backslash in the replacement throws IllegalArgumentException.

SwSwift
let result = "cat catalog concatenate"
    .replacingOccurrences(of: "cat", with: "dog")
print(result) // dog dogalog condogenate

replacingOccurrences(of:with:) replaces every match and is literal by default — pass options: .regularExpression or .caseInsensitive to change the engine. It bridges to NSString, so the range-taking variant speaks UTF-16 offsets; convert with Range(nsRange, in: string) before touching Swift indices.

KtKotlin
fun main() {
    val result = "cat catalog concatenate".replace("cat", "dog")
    println(result) // dog dogalog condogenate
}

Kotlin's replace(CharSequence, CharSequence) replaces every literal occurrence — no first-only trap, no regex by accident. The Regex overloads (replace(regex, "-") or replace(regex) { match -> ... }) are the pattern siblings; there is no stdlib first-only replace, so a one-shot swap means indexOf plus substring stitching.

RbRuby
result = 'cat catalog concatenate'.gsub('cat', 'dog')
puts result # dog dogalog condogenate

sub replaces once; gsub ("global substitution") replaces everywhere — the mnemonic is the g. A String needle is literal, but escape user input with Regexp.escape before passing a Regexp. When the replacement itself contains backslashes or dollar signs, use the block form gsub('cat') { 'dog' } — block results are inserted verbatim with no reference expansion.

ZigZig
const std = @import("std");

pub fn main() !void {
    const input = "cat catalog concatenate";
    const out = try std.heap.page_allocator.alloc(
        u8,
        std.mem.replacementSize(u8, input, "cat", "dog"),
    );
    defer std.heap.page_allocator.free(out);

    const count = std.mem.replace(u8, input, "cat", "dog", out);
    std.debug.print("{s} — {d} replacements\n", .{ out, count }); // dog dogalog condogenate — 3 replacements
}

Two steps by design: replacementSize computes the exact output length (replacements may shrink or grow the buffer), then std.mem.replace writes into your slice and returns the match count. Everything is bytes — the stdlib has no regex, so pattern work needs a third-party package.

Keep going

Read the regex-tokens cheatsheet →