我正在撰寫一些代碼來決議一些 SQL 運算式,但遇到了我自己無法解決的問題。我想替換 SQL 陳述句中的某個單詞,但如果該單詞包含在用單引號或雙引號括起來的短語中,則不替換。我的用例是 SQL 運算式決議,但我認為這更像是一個通用的字串替換。
舉個例子,考慮一下運算式:
select {foo} from Table where {foo} = "This is {foo} today" or {foo} = 'this is {foo} tomorrrow' or {foo} = "it's all '{foo}' to me!"
假設我想替換{foo}
為 string bar
,輸出將是:
select bar from Table where bar = "This is {foo} today" or bar = 'this is {foo} tomorrow' or bar = "it's all '{foo}' to me!"
正如我們所見,所有用{foo}
引號括起來的運算式(單引號或雙引號)都沒有被替換。
我們可以假設引號將被關閉,即不會有雜散的引號浮動(where {foo} = 'un'even"
不是我們需要考慮的用例。)
嵌套引號內的文本不應被替換(因為無論您怎么看,文本都包含在引號內:))該示例在該or {foo} = "it's all '{foo}' to me!"
部分中顯示了一個示例(以及包含三個單引號只是為了好玩)
我對此做了很多研究,用 Javascript(或任何其他語言毫無疑問)做這件事似乎很棘手。這似乎很適合正則運算式,但任何 javascript 解決方案正則運算式與否都會有所幫助。我在堆疊溢位中最接近解決方案的是不要替換正則運算式,如果它被一個字符包圍,但它不是一個足夠接近的匹配來幫助
uj5u.com熱心網友回復:
對于使用 JavaScript 的示例字串,您可以使用帶有回呼的單個模式來檢查捕獲組。
(['"]).*?\1|({foo})
模式匹配:
(['"])
第 1 組,捕獲"
或'
.*?
匹配任何字符,盡可能少\1
匹配第 1 組中捕獲的相同字符|
或者({foo})
{foo}
在第 2 組中捕獲
正則運算式演示
在回呼中檢查組 2。如果存在,則回傳它,否則回傳整個匹配項。
const regex = /(['"]).*?\1|({foo})/g;
const str = `select {foo} from Table where {foo} = "This is {foo} today" or {foo} = 'this is {foo} tomorrrow' or {foo} = "it's all '{foo}' to me!"`;
const result = str.replace(regex, (m, _, g2) => g2 ? "bar" : m);
console.log(result);
uj5u.com熱心網友回復:
您可以'. ?'|\{foo\}
使用回呼對 進行正則運算式替換,并且僅在后一個匹配項中進行替換。請注意,SQL 中的字串文字使用單引號,而不是雙引號。因此,我將重構您的查詢以僅對字串使用單引號。
var sql = "select {foo} from Table where {foo} = 'This is {foo} today' or {foo} = 'this is {foo} tomorrrow' or {foo} = 'it''s all ''{foo}'' to me!'";
var output = sql.replace(/'. ?'|\{foo\}/g, (x) => x.match(/^\{.*\}$/) ? "bar" : x);
console.log(output);
筆記:
- 正則運算式模式首先嘗試匹配單引號中的術語,這確保我們只匹配
{foo}
不匹配字串文字。 - SQL中的文字單引號是通過將它們加倍形成的
''
uj5u.com熱心網友回復:
我懷疑它是否可以直接在您的特定示例上使用唯一的正則運算式來完成,因為它可能有單獨的單引號、交錯的單引號或雙引號、優先級沖突等。根據我的說法,最好的方法是撰寫一個簡單的天真的解決方案適用于您的大多數用例,然后查看是否有優化空間。
Javascript 中的以下內容即使不是最佳的也可以作業(例如,用回呼替換可能不太可讀,但更簡潔):
const source = `select {foo} from Table where {foo} = "This is {foo} today" or {foo} = 'this is {foo} tomorrow' or {foo} = "it's all '{foo}' to me!"`;
const solution = `select bar from Table where bar = "This is {foo} today" or bar = 'this is {foo} tomorrow' or bar = "it's all '{foo}' to me!"`;
const exclusions = [];
const exclusionPatterns = [/\".*?\"/g, /\'.*?\'/g];
let modifiedSource = source;
for (const pattern of exclusionPatterns) {
let matches;
while (true) {
matches = modifiedSource.match(pattern);
if (!matches) {
break;
}
const firstMatch = matches[0];
modifiedSource = modifiedSource.replace(
firstMatch,
`$${exclusions.length}`
);
exclusions.push(firstMatch);
}
}
const destination = modifiedSource.replace(/(\{foo\}) /g, "bar");
let modifiedDestination = destination;
for (const [index, exclusion] of exclusions.entries()) {
modifiedDestination = modifiedDestination.replace(`$${index}`, exclusion);
}
console.log(source);
console.log(modifiedSource);
console.log(modifiedDestination);
console.log(solution);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/519982.html