0

I've have a problem with preg_replace() using arrays.

Basically, I'd like to transpose this string:

$string = "Dm F Bb F Am";

To

$New_string = "F#m D D A C#m";

Here is what I do:

$Find = Array("/Dm/", "/F/", "/Bb/", "/Am/", "/Bbm/", "/A/", "/C/");
$Replace = Array('F#m', 'A', 'D', 'C#m', 'Dm', 'C#', 'E');
$New_string = preg_replace($Find, $Replace, $string);

But I get this result instead:

E##m E# D E# E#m

Problem is that every match is replaced by the following, something like this happens (example for E##m):

Dm -> F#m -> A#m -> C##m -> E##m

Is there any solution to simply change Dm to F#m, F to A, etc ?

4
  • 2
    Looks like a simple str_replace() to me, no preg required Commented Sep 12, 2012 at 10:21
  • thanks but I already tried with str_replace() and the result is exactly the same, it's wrong... Commented Sep 12, 2012 at 10:26
  • Oh right I see what you're getting at. Will answer in a second. Commented Sep 12, 2012 at 10:32
  • I would try to explode the string into an array and replace each item individually in a forEach loop. Commented Sep 12, 2012 at 10:33

2 Answers 2

4

You could use strtr():

<?php
    $string = "Dm F Bb F Am";
    $Find = Array('Dm', 'F', 'Bb', 'Am', 'Bbm', 'A', 'C');
    $Replace = Array('F#m', 'A', 'D', 'C#m', 'Dm', 'C#', 'E');

    $New_string = strtr($string, array_combine($Find, $Replace));

    echo $New_string;

    // F#m A D A C#m
Sign up to request clarification or add additional context in comments.

Comments

1

preg_replace_callback() is probably the simplest way of doing that, you need to do it in a single operation. Something like this:

<?php

$string = "Dm F Bb F Am";

$replacements = array (
    'Dm' => 'F#m',
    'F' => 'A',
    'Bb' => 'D',
    'Am' => 'C#m',
    'Bbm' => 'Dm',
    'A' => 'C#',
    'C' => 'E'
);

$New_string = preg_replace_callback('/\b('.implode('|', array_map('preg_quote', array_keys($replacements), array_fill(0, count($replacements), '/'))).')\b/', function($match) use($replacements) {
    return $replacements[$match[1]];
}, $string);

echo $New_string;

See it working

Now, I am aware that the code above is a little incomprehensible, so let's break it up a bit and see what each individual component does:

// The input string and a map of search => replace
$string = "Dm F Bb F Am";
$replacements = array (
    'Dm' => 'F#m',
    'F' => 'A',
    'Bb' => 'D',
    'Am' => 'C#m',
    'Bbm' => 'Dm',
    'A' => 'C#',
    'C' => 'E'
);

// Get a list of the search strings only
$searches = array_keys($replacements);

// Fill an array with / characters to the same length as the number of search
// strings. This is required for preg_quote() to work properly
$delims = array_fill(0, count($searches), '/');

// Apply preg_quote() to each search string so it is safe to use in the regex
$quotedSearches = array_map('preg_quote', $searches, $delims);

// Build the regex
$expr = '/\b('.implode('|', $quotedSearches).')\b/';

// Define a callback that will translate search matches to replacements
$callback = function($match) use($replacements) {
  return $replacements[$match[1]];
};

// Do the replacement
$New_string = preg_replace_callback($expr, $callback, $string);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.