diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index 997faf2452285ce93ba2b1b10db89ef498047be1..677a678959d3e26be858a73055b65b833614c908 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -170,7 +170,8 @@ void runFileSearch(QFutureInterface<FileSearchResult> &future,
                             while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
                                 res.append(startOfLastLine[i++]);
                             future.reportResult(FileSearchResult(s, lineNr, QString(res),
-                                                          regionPtr - startOfLastLine, sa.length()));
+                                                          regionPtr - startOfLastLine, sa.length(),
+                                                          QStringList()));
                             ++numMatches;
                         }
                     }
@@ -229,7 +230,8 @@ void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
             int pos = 0;
             while ((pos = expression.indexIn(line, pos)) != -1) {
                 future.reportResult(FileSearchResult(s, lineNr, line,
-                                              pos, expression.matchedLength()));
+                                              pos, expression.matchedLength(),
+                                              expression.capturedTexts()));
                 pos += expression.matchedLength();
             }
             ++lineNr;
@@ -259,3 +261,36 @@ QFuture<FileSearchResult> Utils::findInFilesRegExp(const QString &searchTerm, co
     return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
             (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);
 }
+
+QString Utils::expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts)
+{
+    QString result;
+    int numCaptures = capturedTexts.size() - 1;
+    for (int i = 0; i < replaceText.length(); ++i) {
+        QChar c = replaceText.at(i);
+        if (c == QLatin1Char('\\') && i < replaceText.length() - 1) {
+            c = replaceText.at(++i);
+            if (c == QLatin1Char('\\')) {
+                result += QLatin1Char('\\');
+            } else if (c == QLatin1Char('&')) {
+                result += QLatin1Char('&');
+            } else if (c.isDigit()) {
+                int index = c.unicode()-'1';
+                if (index < numCaptures) {
+                    result += capturedTexts.at(index+1);
+                } else {
+                    result += QLatin1Char('\\');
+                    result += c;
+                }
+            } else {
+                result += QLatin1Char('\\');
+                result += c;
+            }
+        } else if (c == QLatin1Char('&')) {
+            result += capturedTexts.at(0);
+        } else {
+            result += c;
+        }
+    }
+    return result;
+}
diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h
index e7f91a6719c50de779c3771cd8f33ae8973186f3..f2860e34e0147c4bb6990326ca53ef1da539f360 100644
--- a/src/libs/utils/filesearch.h
+++ b/src/libs/utils/filesearch.h
@@ -43,8 +43,15 @@ class QTCREATOR_UTILS_EXPORT FileSearchResult
 {
 public:
     FileSearchResult() {}
-    FileSearchResult(QString fileName, int lineNumber, QString matchingLine, int matchStart, int matchLength)
-            : fileName(fileName), lineNumber(lineNumber), matchingLine(matchingLine), matchStart(matchStart), matchLength(matchLength)
+    FileSearchResult(QString fileName, int lineNumber, QString matchingLine,
+                     int matchStart, int matchLength,
+                     QStringList regexpCapturedTexts)
+            : fileName(fileName),
+            lineNumber(lineNumber),
+            matchingLine(matchingLine),
+            matchStart(matchStart),
+            matchLength(matchLength),
+            regexpCapturedTexts(regexpCapturedTexts)
     {
     }
     QString fileName;
@@ -52,6 +59,7 @@ public:
     QString matchingLine;
     int matchStart;
     int matchLength;
+    QStringList regexpCapturedTexts;
 };
 
 QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFiles(const QString &searchTerm, const QStringList &files,
@@ -60,6 +68,8 @@ QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFiles(const QString &sear
 QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFilesRegExp(const QString &searchTerm, const QStringList &files,
     QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap = QMap<QString, QString>());
 
+QTCREATOR_UTILS_EXPORT QString expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts);
+
 } // namespace Utils
 
 #endif // FILESEARCH_H
diff --git a/src/plugins/find/basetextfind.cpp b/src/plugins/find/basetextfind.cpp
index d2ddfc0441856d79ad392f65804de325ac84c5b2..86dd69e33c666b81a218ffdfe58b3efd805403d2 100644
--- a/src/plugins/find/basetextfind.cpp
+++ b/src/plugins/find/basetextfind.cpp
@@ -30,6 +30,7 @@
 #include "basetextfind.h"
 
 #include <utils/qtcassert.h>
+#include <utils/filesearch.h>
 
 #include <QtGui/QTextBlock>
 #include <QtGui/QPlainTextEdit>
@@ -152,40 +153,6 @@ IFindSupport::Result BaseTextFind::findStep(const QString &txt, IFindSupport::Fi
     return found ? Found : NotFound;
 }
 
-namespace {
-    QString expandRegExpReplacement(const QString &replaceText, const QRegExp &regexp)
-    {
-        QString result;
-        for (int i = 0; i < replaceText.length(); ++i) {
-            QChar c = replaceText.at(i);
-            if (c == QLatin1Char('\\') && i < replaceText.length() - 1) {
-                c = replaceText.at(++i);
-                if (c == QLatin1Char('\\')) {
-                    result += QLatin1Char('\\');
-                } else if (c == QLatin1Char('&')) {
-                    result += QLatin1Char('&');
-                } else if (c.isDigit()) {
-                    int index = c.unicode()-'1';
-                    if (index < regexp.numCaptures()) {
-                        result += regexp.cap(index+1);
-                    } else {
-                        result += QLatin1Char('\\');
-                        result += c;
-                    }
-                } else {
-                    result += QLatin1Char('\\');
-                    result += c;
-                }
-            } else if (c == QLatin1Char('&')) {
-                result += regexp.cap(0);
-            } else {
-                result += c;
-            }
-        }
-        return result;
-    }
-}
-
 bool BaseTextFind::replaceStep(const QString &before, const QString &after,
     IFindSupport::FindFlags findFlags)
 {
@@ -196,7 +163,7 @@ bool BaseTextFind::replaceStep(const QString &before, const QString &after,
                    usesRegExp ? QRegExp::RegExp : QRegExp::FixedString);
 
     if (regexp.exactMatch(cursor.selectedText())) {
-        QString realAfter = usesRegExp ? expandRegExpReplacement(after, regexp) : after;
+        QString realAfter = usesRegExp ? Utils::expandRegExpReplacement(after, regexp.capturedTexts()) : after;
         int start = cursor.selectionStart();
         cursor.insertText(realAfter);
         if ((findFlags&IFindSupport::FindBackward) != 0)
@@ -226,7 +193,7 @@ int BaseTextFind::replaceAll(const QString &before, const QString &after,
         editCursor.setPosition(found.selectionStart());
         editCursor.setPosition(found.selectionEnd(), QTextCursor::KeepAnchor);
         regexp.exactMatch(found.selectedText());
-        QString realAfter = usesRegExp ? expandRegExpReplacement(after, regexp) : after;
+        QString realAfter = usesRegExp ? Utils::expandRegExpReplacement(after, regexp.capturedTexts()) : after;
         editCursor.insertText(realAfter);
         found = findOne(regexp, editCursor, IFindSupport::textDocumentFlagsForFindFlags(findFlags));
     }
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index 2bacef7cb36796a7cad84cef4b34aa9d18ad580f..650c13b0206a2170afb331feb59e5118e01ff653 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -150,7 +150,8 @@ void BaseFileFind::displayResult(int index) {
                               result.lineNumber,
                               result.matchingLine,
                               result.matchStart,
-                              result.matchLength);
+                              result.matchLength,
+                              result.regexpCapturedTexts);
     if (m_resultLabel)
         m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
 }
@@ -280,7 +281,7 @@ void BaseFileFind::openEditor(const Find::SearchResultItem &item)
 
 static void applyChanges(QTextDocument *doc, const QString &text, const QList<Find::SearchResultItem> &items)
 {
-    QList<QTextCursor> cursors;
+    QList<QPair<QTextCursor, QString> > changes;
 
     foreach (const Find::SearchResultItem &item, items) {
         const int blockNumber = item.lineNumber - 1;
@@ -289,24 +290,31 @@ static void applyChanges(QTextDocument *doc, const QString &text, const QList<Fi
         const int cursorPosition = tc.position() + item.searchTermStart;
 
         int cursorIndex = 0;
-        for (; cursorIndex < cursors.size(); ++cursorIndex) {
-            const QTextCursor &tc = cursors.at(cursorIndex);
+        for (; cursorIndex < changes.size(); ++cursorIndex) {
+            const QTextCursor &otherTc = changes.at(cursorIndex).first;
 
-            if (tc.position() == cursorPosition)
+            if (otherTc.position() == cursorPosition)
                 break;
         }
 
-        if (cursorIndex != cursors.size())
+        if (cursorIndex != changes.size())
             continue; // skip this change.
 
         tc.setPosition(cursorPosition);
         tc.setPosition(tc.position() + item.searchTermLength,
                        QTextCursor::KeepAnchor);
-        cursors.append(tc);
+        QString substitutionText;
+        if (item.userData.canConvert<QStringList>() && !item.userData.toStringList().isEmpty())
+            substitutionText = Utils::expandRegExpReplacement(text, item.userData.toStringList());
+        else
+            substitutionText = text;
+        changes.append(QPair<QTextCursor, QString>(tc, substitutionText));
     }
 
-    foreach (QTextCursor tc, cursors)
-        tc.insertText(text);
+    for (int i = 0; i < changes.size(); ++i) {
+        QPair<QTextCursor, QString> &cursor = changes[i];
+        cursor.first.insertText(cursor.second);
+    }
 }
 
 QStringList BaseFileFind::replaceAll(const QString &text,