Currency Symbol Regex in Java: Match Any Sign With \p{Sc}

Currency symbol regex for Java with \p{Sc}. Find dollar, euro and rupee signs, extract prices and avoid the two dollar sign traps in Java 25.

Characters that the regex p{Sc} matches, such as dollar, euro, pound, yen, rupee and bitcoin signs, and text it does not match, such as USD, Rs and percent

The currency symbol regex \p{Sc} matches any currency symbol in Java, such as the dollar, euro, pound, yen, rupee and bitcoin signs, and every other character that Unicode classifies as “Currency_Symbol”. The syntax \p{…} selects characters by a Unicode property, and Sc is the short name of the general category “Symbol, currency”.

We use \p{Sc} to find, count, remove or validate currency signs in prices, invoices and imported text without listing the symbols one by one. In a Java string literal, the backslash is doubled, so the pattern is written as “\\p{Sc}”.

The following example checks single characters and scans a price list. Non-ASCII symbols in the code are Java escapes, so \u20ac is the euro sign and \u00a5 is the yen sign, and the list shows each match as its code point.

String prices = "Apple $5, Banana \u20ac3, Cherry \u00a5200";

boolean dollar = "$".matches("\\p{Sc}");                          // true
boolean euro = "\u20ac".matches("\\p{Sc}");                       // true
boolean percent = "%".matches("\\p{Sc}");                         // false

Pattern currency = Pattern.compile("\\p{Sc}");
List<String> found = currency.matcher(prices).results().map(r -> "U+%04X".formatted(r.group().codePointAt(0))).toList();   // [U+0024, U+20AC, U+00A5]
boolean none = currency.matcher("hello").find();                  // false
String stripped = prices.replaceAll("\\p{Sc}", "");               // "Apple 5, Banana 3, Cherry 200"

Notice that one short pattern finds the dollar, euro and yen signs, and that the same pattern removes them with replaceAll(). Next we look at symbol positions, the exact set of characters \p{Sc} covers in Java 25, the other spellings of the pattern, amounts with their symbols and the two dollar sign traps. Readers new to Unicode properties in patterns can start with our Java regex tutorial.

1. Finding Currency Symbols and Their Positions

To check whether a text contains any currency symbol, we call find(). To list them, Matcher.results() returns a stream of matches, and each match knows its start() index. A Pattern is immutable and thread-safe, so we compile it once into a constant and reuse it.

final class Prices {
    static final Pattern CURRENCY = Pattern.compile("\\p{Sc}");

    static List<Integer> symbolPositions(String text) {
        return CURRENCY.matcher(text).results().map(MatchResult::start).toList();
    }
}
String prices = "Apple $5, Banana \u20ac3, Cherry \u00a5200";
List<Integer> positions = Prices.symbolPositions(prices);          // [6, 17, 28]
long count = Prices.CURRENCY.matcher(prices).results().count();   // 3

The pattern matches the symbol only, not the amount after it. The pattern in section 4 extends it to capture amounts such as “$1,250.00”.

2. Which Characters \p{Sc} Matches

Java 25 implements Unicode 16.0, which has 63 characters in the currency symbol category. A loop over every code point with Character.getType() returns the same 63 characters as \p{Sc}. They fall into four groups.

  • The common signs are the dollar, cent, pound, yen and euro signs and the generic currency sign U+00A4.
  • Newer signs include the Indian rupee (U+20B9), the ruble (U+20BD), the bitcoin sign (U+20BF) and the som sign (U+20C0).
  • Signs from other scripts include the Thai baht (U+0E3F) and the rial sign (U+FDFC).
  • Full-width and small variants appear in East Asian text, such as the full-width dollar sign (U+FF04).
Characters that the regex p{Sc} matches, such as dollar, euro, pound, yen, rupee and bitcoin signs, and text it does not match, such as USD, Rs and percent
The pattern matches one symbol character at a time, and currency codes written with letters never match

Currencies written with letters are not currency symbols. Codes and abbreviations such as “USD”, “CHF”, “Rs” or “kr” consist of ordinary letters, so \p{Sc} does not match them. Percent and number signs are not currency symbols either.

boolean rupee = "\u20b9".matches("\\p{Sc}");            // true, Indian rupee sign
boolean bitcoin = "\u20bf".matches("\\p{Sc}");          // true, bitcoin sign
boolean wideDollar = "\uff04".matches("\\p{Sc}");       // true, full-width dollar sign
boolean rs = "Rs".matches("\\p{Sc}+");                  // false
boolean chf = "CHF".matches("\\p{Sc}+");                // false
boolean percent = "%".matches("\\p{Sc}");               // false

The category grows with each Unicode version, and Java follows only with a new JDK release. Unicode 17.0 (September 2025) added the new Saudi riyal sign at U+20C1. Java 25 still uses Unicode 16.0, where U+20C1 is unassigned, so \p{Sc} does not match it yet.

int som = Character.getType(0x20C0);              // 26, CURRENCY_SYMBOL (som sign, Unicode 14)
int riyal = Character.getType(0x20C1);            // 0, UNASSIGNED in Java 25

3. Other Ways to Write the Pattern

Java accepts several spellings for the same category, plus two related properties with a different meaning. Picking the wrong one is a common source of missed matches.

  • The spellings \p{Sc}, \p{IsSc}, \p{gc=Sc} and \p{general_category=Sc} all mean the same category.
  • The property \p{S} matches any symbol, which also includes math symbols such as “+”, arrows and emoji.
  • The block \p{InCurrencySymbols} covers U+20A0 to U+20CF. It contains the euro sign but not the dollar, pound or yen signs, which belong to older blocks.

The long category name does not work in Java. The call Pattern.compile(“\\p{Currency_Symbol}”) throws a PatternSyntaxException with the message “Unknown character property name {Currency_Symbol}”.

boolean euroBlock = "\u20ac".matches("\\p{InCurrencySymbols}");   // true
boolean dollarBlock = "$".matches("\\p{InCurrencySymbols}");       // false, not in that block
boolean plus = "+".matches("\\p{S}");                              // true, a math symbol
boolean gc = "$".matches("\\p{gc=Sc}");                            // true
Pattern longName = Pattern.compile("\\p{Currency_Symbol}");        // PatternSyntaxException

The same category works in other regex engines. JavaScript has supported Unicode character class escapes since ES2018, so the pattern there is /\p{Sc}/u, where the u flag is required.

4. Matching an Amount With Its Currency Symbol

Prices are written in two orders. English texts put the symbol first, as in “$1,250.00”, whereas many European languages put it after the number and use a comma as the decimal separator, as in “99,90” followed by the euro sign. Named groups such as (?<symbol>…) let us read the symbol and the amount by name.

PartMeaning
(?<symbol>\p{Sc})The currency symbol, captured as symbol
\s?An optional space
\d{1,3}One to three digits before the first thousands separator
(?:,\d{3})*Groups of a comma and three digits, as in “1,250”
(?:\.\d{2})?Optional cents, as in “.00”

Say a travel expense app reads hotel bills that people forward by email. One bill says “Pay $1,250.00”, another one lists “99,90” with the euro sign after it. The app needs the amount and the symbol of each price before it converts them.

Pattern symbolFirst = Pattern.compile("(?<symbol>\\p{Sc})\\s?(?<amount>\\d{1,3}(?:,\\d{3})*(?:\\.\\d{2})?)");
Pattern symbolLast = Pattern.compile("(?<amount>\\d+(?:,\\d{2})?)\\s?(?<symbol>\\p{Sc})");
String bill = "Pay $1,250.00 or 99,90\u20ac or \u00a5 500 today";

List<String> before = symbolFirst.matcher(bill).results().map(r -> r.group("amount")).toList();   // [1,250.00, 500]
List<String> after = symbolLast.matcher(bill).results().map(r -> r.group("amount")).toList();     // [99,90]

The two patterns find amounts in text, but they do not parse them. To turn “1,250.00” into a number, we use java.text.NumberFormat or DecimalFormat with the right Locale, because the meaning of “,” and “.” depends on the locale.

5. Two Dollar Sign Traps

The dollar sign is a currency symbol and a regex metacharacter at the same time. In a pattern, an unescaped $ means “end of input”, not a dollar sign. We write \$ (the Java string “\\$”) or put it in a character class, [$].

boolean anchor = "cost $5".matches(".*$5");          // false, $ is an anchor here
boolean escaped = "cost $5".matches(".*\\$5");       // true
boolean inClass = "cost $5".matches(".*[$]5");       // true

The replacement string of replaceAll() has its own syntax, where $1 inserts the text of captured group 1. A dollar sign in a replacement string is a group reference, so the replacement “$5” throws an IndexOutOfBoundsException when the pattern has no fifth group.

String broken = "cost 5".replaceAll("5", "$5");                            // IndexOutOfBoundsException: No group 5
String quoted = "cost 5".replaceAll("5", Matcher.quoteReplacement("$5"));   // "cost $5"
String backslash = "cost 5".replaceAll("5", "\\$5");                        // "cost $5"

The method Matcher.quoteReplacement() escapes every $ and backslash in a replacement that comes from data, such as a formatted price.

6. From a Symbol to a Currency Code

A symbol does not identify a currency. The “$” sign is used for the US, Canadian, Australian and many other dollars, and the yen sign also stands for the Chinese yuan. The java.util.Currency class works the other way round, from an ISO 4217 code to the symbol that a locale displays.

String usInUs = Currency.getInstance("USD").getSymbol(Locale.US);                 // "$"
String usInCanada = Currency.getInstance("USD").getSymbol(Locale.CANADA);         // "US$"
String cadInCanada = Currency.getInstance("CAD").getSymbol(Locale.CANADA);        // "$"
String chfInSwiss = Currency.getInstance("CHF").getSymbol(Locale.of("de", "CH")); // "CHF", no symbol

When the currency matters, as in payments or invoices, we store the three-letter code next to the amount and use the symbol only for display.

7. Currency Symbol Regex FAQs

Developers who parse prices in Java often ask about these cases.

7.1. How Do We Match Only the Dollar Sign in a Regex?

We escape it as \\$ in the Java string or write [$]. An unescaped $ is the end-of-input anchor, as section 5 shows.

7.2. Does \p{Sc} Match Currency Codes Such as USD or EUR?

No. Currency codes are made of letters, and \p{Sc} matches only symbol characters. To find codes, we add an alternation with the codes we accept, for example (?:\p{Sc}|USD|EUR|CHF).

7.3. What Is the Difference Between \p{Sc} and \P{Sc}?

The uppercase \P{Sc} is the negation, so it matches every character that is not a currency symbol.

int symbolCount = "Total $5 + \u20ac3".replaceAll("\\P{Sc}", "").length();   // 2, the dollar and euro signs

7.4. Does \p{Sc} Need the UNICODE_CHARACTER_CLASS Flag?

No. Unicode categories such as \p{Sc} work without any flag. The flag Pattern.UNICODE_CHARACTER_CLASS changes only the predefined classes such as \w, \d and \s.

7.5. Why Does My Currency Symbol Show as a Question Mark?

The source file or the console uses a different encoding than the text. We write non-ASCII symbols as \u escapes in code, or compile with UTF-8, which is the default since Java 18 (JEP 400).

8. Conclusion

The regex \p{Sc} matches every character in the Unicode currency symbol category, 63 of them in Java 25, from “$” and the euro sign to the rupee and bitcoin signs. It does not match currency codes written with letters, and it learns new symbols only when the JDK moves to a newer Unicode version.

To capture prices, we combine \p{Sc} with a number pattern and named groups. In patterns we escape the dollar sign as \$, and in replacements we use Matcher.quoteReplacement().

9. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.