簡體   English   中英

正則表達式檢測整個字符串是否是占位符

[英]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+時,這將是最好的。

使用正則表達式無法匹配任意深度的嵌套結構。 使用單個正則表達式最多可以匹配有限數量的嵌套部分,盡管您的模式可能會非常難看。

另一種方法是多次應用一個更簡單的模式,直到你得到答案。 例如:

  1. 將與\$\{[^}]*\} (或\$\{.*?\} )匹配的所有內容替換為空字符串(空字符串)
  2. 重復直到模式不再匹配

如果字符串現在為空,則該值為“有效”。 如果字符串不為空,則值為“無效”。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM