[英]Regex detect if entire string is a placeholder
我正在嘗試編寫一個應該檢測“整個字符串是占位符”的正則表達式。
此處有效占位符的示例是${var}
此處無效占位符的示例是${var}-sometext
因為占位符只是文本的一部分
我目前擁有的正則表達式是^\$\{(.+)\}$
這適用於正常情況。 例如
1 | ${變量} | 正則表達式匹配 | 期待✅ |
2 | ${var} 文本 | 正則表達式不匹配 | 期待✅ |
甚至適用於嵌套占位符
3 | ${var-${nestedVar}} | 正則表達式匹配 | 期待✅ |
失敗的地方是字符串是否以占位符開頭和結尾,例如
4 | ${var1}-txt-${var2} | 正則表達式匹配 | 沒想到❌ |
基本上即使整個字符串不是占位符,正則表達式也將其視為一個,因為它以${
開頭並以}
結尾
我可以嘗試通過將.+
替換為[^$]+
之類的東西來排除美元來解決它,但這會破壞示例 3 中的嵌套用例。
我該如何解決這個問題?
編輯
為上下文添加一些代碼
public static final Pattern PATTERN = Pattern.compile("^\\$\\{(.+)\\}$");
Matcher matcher = PATTERN.matcher(placeholder);
boolean isMatch = matcher.find();
從你的例子中,我認為你需要避免貪婪的量詞:
\$\{(.+?)\}
注意?
+
之后是不情願的量詞: https://docs.oracle.com/javase/tutorial/essential/regex/quant.html
那應該匹配${var1}-txt-${var2}
現在,如果您同時使用^
和$
,這將失敗。
請注意,您還可以使用commons-text 中的 StringSubstitutor來執行類似的工作(它將處理解析,您可以使用捕獲變量的Lookup
)。
編輯評論:鑒於 Java 正則表達式不支持遞歸,如果您想匹配所有 4 個案例,則必須在此處硬編碼部分遞歸:
\$\{([^{}-]+)(?:|-\$\{([^{}-]+)\})\}
第一部分匹配一個變量,忽略{}
和-
。 另一部分匹配一個空的默認值,或者一個插值。
如果你需要捕捉${a-${b-${c}}}
你將不得不添加另一個你應該避免的層:為了做復雜的正則表達式而做復雜的正則表達式只會是維護的痛苦(只有上面的正則表達式的一級遞歸很難閱讀)
如果您需要處理遞歸,我認為您沒有其他選擇可以自己使用如下代碼:
void parse(String pattern) {
if (pattern.startsWith("${") && pattern.endsWith("}")) {
// remove ${ and }
var content = pattern.substring(2, pattern.length() - 2 - 1);
var n = content.indexOf('-');
String leftVar = content;
if (n != -1) {
leftVar = content.substring(0, n);
// perform recursion
parse(content.substring(n+1));
}
// return whatever you need
}
或者使用已經存在的東西。
static boolean isPlaceHolder(String s) {
return s.matches("\\$\\{[^}]*\\}");
}
或針對多種用途進行了優化:
private static final Pattern PLACE_HOLDER_PATTERN =
Pattern.compile("\\$\\{[^}]*\\}");
static boolean isPlaceHolder(String s) {
return PLACE_HOLDER_PATTERN.matcher(s).matches();
}
^...$
。 相對於find 。"${x}, ${y}"
。 當占位符僅用於變量\\w+
時,這將是最好的。使用正則表達式無法匹配任意深度的嵌套結構。 使用單個正則表達式最多可以匹配有限數量的嵌套部分,盡管您的模式可能會非常難看。
另一種方法是多次應用一個更簡單的模式,直到你得到答案。 例如:
\$\{[^}]*\}
(或\$\{.*?\}
)匹配的所有內容替換為空字符串(空字符串)如果字符串現在為空,則該值為“有效”。 如果字符串不為空,則值為“無效”。
private static final Pattern PATTERN = Pattern.compile("\\$\\{.*?\\}");
public boolean isValid(String value) {
while (true) {
String newValue = PATTERN.matcher(value).replaceAll("");
if (newValue.equals(value))
break;
value = newValue;
}
return value.isEmpty();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.