Искать регулярное выражение после заданной позиции
Нужно в тексте найти и заменить на "Х" все комбинации цифр (например обрывки номеров карт), но в тексте может сначала встретится нужное число типа суммы оплаты в $. Это число трогать не надо и нужно продолжить поиск после этой суммы. Переназначение RegExp.lastIndex не срабатывает, функция опять находит сумму и из цикла while, естественно, не выходит. До этого этот код написал на VB.net, там при запуске поиска можно задать позицию начала поиска и все нормально работало.
String.prototype.toX = function (index) {
return this.slice(0, index) + 'X' + this.slice(index + 1);
}
regex = new RegExp(/(\b\d{3,5}\d[\?\.])|(\b\d{3,4}-\d{3}-\d{4}\.)|(\b\d{3,4}-\d{4}\.)|(( \d,?){4})/);
mm = strText.match(regex) || [];
while (mm.length > 0) {
// ищем начало комбинации
j = mm.index
cn = strText[j]
while ((!isNaN(cn) || cn === "-" || cn === "." || cn === ",") && cn != ' ') {
j -= 1;
cn = strText[j];
}
//возможно цифры это сумма в $
if (cn === '$') {
regex.lastIndex = j + mm[0].length;
mm = strText.match(regex) || [];
continue;
}
// заменяем на X
for (j = mm.index; j < (mm.index + mm[0].length); j++) {
if (strText[j] != "-" && strText[j] != "." && strText[j] != ",") {
strText = strText.toX(j);
}
}
mm = strText.match(regex) || [];
}
На вход подается примерно такой текст. Это транскрипт телефонного разговора с клиентом:
"Caller: Hello? Agent: Hello. Yeah, this is Tyler with СС company. I just want to get all your I have all your information out in here. I just want to finish processing your order. Caller: Oh, thank you. Okay. I can give you my card number. Agent: Yeah. So really quick. I just want to double check your zip code really quick so I have merit. British. It's British Columbia. Caller: Yeah. Agent: And the zip code. So I have V, 1 K, 1 B 8. Caller: That's right. Agent: Okay, cool. Just want to make sure because it gives me, like, a weird error sign when I do it in our system, but it'll be fine. I just want to make sure the zip code is correct for that. Except. Caller: I see because sometimes shows, like, 1 R, but male comes like that. Agent: Yeah, I get an R a lot of the times when I was looking at it. So I just want to make sure that that was the right zip code because it'll still send. I just want to make sure it's correct. Caller: Yeah, male comes down this 1 too. Agent: Okay, cool. And the billing address and everything is the same, correct? Caller: Yeah. That's righteous. Agent: Okay, let me see what the estimates I have for the shipping are generating. Okay. It is the cheapest, fastest option I have is FedEx rate priority, which will get it's $535. And it should be there. It's estimating it's going to get there on the 14th. And that's for the 8 Pails that we have. Correct. It's 8. Caller: Yeah, 8 fields. Yeah. Agent: Okay, cool. I just want to make sure you're okay with that. Caller: It comes on 14th. Agent: It should be there as long as FedEx doesn't have any issues. They had some weather issues last week with all the rain that was happening. So it should be there the 14th. It should process out of our facility tomorrow. So is it this? Yeah, that's as fast as I can get it there with it getting through customs and everything. So if you still want to go with that, we can process it. But that's the quickest shipping option I'm seeing. Caller: Yeah, just hold. Agent: Okay. Caller: Up. Harry. Yeah, Jonah. Three Krono 1414. So dolan payment, but they actually told me that it's going to take 5 days, like 3 days certifier and 2 days for a payment process. Agent: Well, it could. I'm just telling you what FedEx is telling me as an estimate. I'm just reading know we use FedEx Freight. I'm just telling you what FedEx is telling me. That's the fastest, cheapest option to get it there, and it's the fastest. That's what it's telling me. It very well could be there faster. I'm just saying it said it should be delivered no later than that. Date. Caller: Her estimate of 14. Okay. Yeah. Okay, that's fine. Agent: Okay. The name on the card, is it the same as the order? Yes. Okay. And then I am ready for that card number whenever you have a chance. Caller: Hargenda singh. Yeah, sure. And underneath is a Duke Sweets restaurant. Agent: Okay, that's fine. Yeah, that's fine. Okay. Caller: On the card? Yeah. Okay, are you ready? Agent: Yes, ma'am. All it. Caller: Okay. 1234-5678. Agent: Okay. Caller: 3308-3483. Agent: All right, I'll read this back to you really quick. It's a visa, so I have 1234-5678-3308-3483. Correct. Okay, and what is the expiration date on that card? Caller: Yeah, that's right. 2020. Agent: 20220. Caller: Two. Yeah. Zero 2. Agent: Okay, I have. I have. February 2020. Caller: Yeah, that's right. Agent: Okay, and what is the CVC on the security code? Caller: 123123. Agent: Okay, I'm going to process this really quick. We'll make sure this goes through. Caller: Yeah, sure. So how much will we totally. Agent: It was it's $3,815.65. I just got an error saying insufficient funds on the card, though. It. Caller: Just hold on, let me check, please. Agent: It. Caller: Available credit should be more than that. Should we work? I don't know why they showing no. Can you try again, please? Agent: Yeah, sure. I can try. I'll read back the card to make sure I have the right card and expiration I have 1234-5678-3308-3483, and it's. Caller: Yeah, sure. Can yeah. Agent: The expiration date and 1, 2, 3 is the CBC code. Okay, I will try it 1 more time. Yeah, I still get that same error code as the insufficient funds when I go to place the order. Caller: Okay. Agent: I can what I can do is I can save this order, and if you want to go just work that out with the card, or if there's something happening with it, I can save it, and then we can just pull it up and we can just process it once that I'll be available all evening. You just give me a call, and I can get this order still processed this evening, if that works for you. Oh, no, you just call me whenever. I'll be available. This goes through my direct line in the evening, so I'll be available to help process this order. Caller: You okay? Sure. I'll phone you in 5 minutes. Agent: Okay, yeah, just give me a call back, all right? Yes, ma'am. Bye. Caller: Okay, thank you. Thank you."
Ответы (2 шт):
Не вижу смысла в циклах. Метод replace() довольно мощный и гибкий инструмент. Регулярное выражение для вашего случая:
/(?<![\d$])\d{4}(?=[., -])/g
В примере ниже, добавлены теги для наглядности (запустите сниппет, вставьте в поле нужный текст, разверните сниппет на всю страницу):
// str.replace( /(?<![\d$])\d{4}(?=[., -])/g , `✕✕✕✕`)
/* For example only --> */ function fHideNumb(str) { result.innerHTML = str.replace(/(?<![\d$])\d{4}(?=[., -])/g, `<mark>✕✕✕✕</mark>`).replace(/(Caller|Agent)(?=:)/g, `<p>$1`) };
/* For example only --> */ p { margin: .25em; padding: .5em .25em } p:nth-of-type(odd) { background:#c004 } p:nth-of-type(even) { background:#0904 }
<!-- For example only --> <textarea oninput="fHideNumb(this.value)"></textarea><output id="result"></output>
Заметьте, когда Agent запрашивает CVC и уточняет срок действия карты, то эти числа не подходят под маску и не заменяются, что на мой взгляд, является недостатком такого подхода к анализу.
В общем решил я свою проблему через RegExp.exec функцию. Моя ошибка была в том, что в регулярном выражении нужно обязательно устанавливать флаг /g, тогда RegExp.lastIndex нормально работает и можно задавать место начала поиска.