diff --git a/packages/loot-core/src/server/accounts/rules.test.ts b/packages/loot-core/src/server/accounts/rules.test.ts
index 556230081aba952e8a286b0ab40f8e9b7b3a5222..392add3ff8a088c3dad0350d3aaceb328ea3b62e 100644
--- a/packages/loot-core/src/server/accounts/rules.test.ts
+++ b/packages/loot-core/src/server/accounts/rules.test.ts
@@ -47,6 +47,9 @@ describe('Condition', () => {
     let cond = new Condition('contains', 'name', 'foo', null, fieldTypes);
     expect(cond.eval({ name: null })).toBe(false);
 
+    cond = new Condition('matches', 'name', '^fo*$', null, fieldTypes);
+    expect(cond.eval({ name: null })).toBe(false);
+
     cond = new Condition('oneOf', 'name', ['foo'], null, fieldTypes);
     expect(cond.eval({ name: null })).toBe(false);
 
@@ -69,6 +72,9 @@ describe('Condition', () => {
     cond = new Condition('contains', 'name', 'foo', null, fieldTypes);
     expect(cond.eval({ date: '2020-01-01' })).toBe(false);
 
+    cond = new Condition('matches', 'name', '^fo*$', null, fieldTypes);
+    expect(cond.eval({ date: '2020-01-01' })).toBe(false);
+
     spy.mockRestore();
   });
 
@@ -223,6 +229,20 @@ describe('Condition', () => {
     expect(cond.eval({ name: 'bfoo' })).toBe(true);
     expect(cond.eval({ name: 'bfo' })).toBe(false);
     expect(cond.eval({ name: 'f o o' })).toBe(false);
+
+    cond = new Condition('matches', 'name', '^fo*$', null, fieldTypes);
+    expect(cond.eval({ name: 'bar foo baz' })).toBe(false);
+    expect(cond.eval({ name: 'bar FOOb' })).toBe(false);
+    expect(cond.eval({ name: 'foo' })).toBe(true);
+    expect(cond.eval({ name: 'foob' })).toBe(false);
+    expect(cond.eval({ name: 'bfoo' })).toBe(false);
+    expect(cond.eval({ name: 'bfo' })).toBe(false);
+    expect(cond.eval({ name: 'f o o' })).toBe(false);
+  });
+
+  test('matches handles invalid regex', () => {
+    const cond = new Condition('matches', 'name', 'fo**', null, fieldTypes);
+    expect(cond.eval({ name: 'foo' })).toBe(false);
   });
 
   test('number validates value', () => {
diff --git a/packages/loot-core/src/server/accounts/rules.ts b/packages/loot-core/src/server/accounts/rules.ts
index b5fbde95d68e78e3b19948599749a2a917759421..467dc7bc80133d5fa7aef6ff42dfee71e1600d2b 100644
--- a/packages/loot-core/src/server/accounts/rules.ts
+++ b/packages/loot-core/src/server/accounts/rules.ts
@@ -162,7 +162,7 @@ const CONDITION_TYPES = {
         assert(
           Array.isArray(value),
           'no-empty-array',
-          `oneOf must have an array value (field: ${fieldName}): ${JSON.stringify(
+          `${op} must have an array value (field: ${fieldName}): ${JSON.stringify(
             value,
           )}`,
         );
@@ -173,7 +173,7 @@ const CONDITION_TYPES = {
         assert(
           typeof value === 'string' && value.length > 0,
           'no-empty-string',
-          `contains must have non-empty string (field: ${fieldName})`,
+          `${op} must have non-empty string (field: ${fieldName})`,
         );
       }
 
@@ -420,6 +420,16 @@ export class Condition {
           );
         }
         return fieldValue <= extractValue(this.value);
+      case 'matches':
+        if (fieldValue === null) {
+          return false;
+        }
+        try {
+          return new RegExp(this.value).test(fieldValue);
+        } catch (e) {
+          console.log('invalid regexp in matches condition', e);
+          return false;
+        }
       default:
     }
 
diff --git a/upcoming-release-notes/3287.md b/upcoming-release-notes/3287.md
new file mode 100644
index 0000000000000000000000000000000000000000..a1b272403c4781a0403875b8d49dc8dab1d68cf8
--- /dev/null
+++ b/upcoming-release-notes/3287.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [psybers, jameshurst]
+---
+
+Apply regular expression conditions to imported transactions.