문자열을 검색하고 모든 발생 %FirstName%
과 %PolicyAmount%
데이터베이스에서 가져온 값으로 바꿔야 합니다. 문제는 FirstName의 대소 문자가 다양하다는 것입니다. 그 String.Replace()
방법 을 사용하지 못하게합니다 . 제안하는 주제에 대한 웹 페이지를 보았습니다.
Regex.Replace(strInput, strToken, strReplaceWith, RegexOptions.IgnoreCase);
그러나 나는 시도하고 대체 어떤 이유 %PolicyAmount%
와 함께 $0
, 교체는 발생하지 않았다. 달러 기호가 정규식에서 예약 된 문자와 관련이 있다고 가정합니다.
정규식 특수 문자를 처리하기 위해 입력을 살균하지 않는 다른 방법이 있습니까?
답변
MSDN
$ 0- “그룹 번호 번호 (10 진수)와 일치하는 마지막 하위 문자열을 대체합니다.”
.NET 정규식에서 그룹 0은 항상 전체 일치합니다. 리터럴 $의 경우
string value = Regex.Replace("%PolicyAmount%", "%PolicyAmount%", @"$$0", RegexOptions.IgnoreCase);
답변
처럼 보인다 string.Replace
해야 걸리는 과부하가 StringComparison
인수를. 그렇지 않기 때문에 다음과 같이 시도 할 수 있습니다.
public static string ReplaceString(string str, string oldValue, string newValue, StringComparison comparison)
{
StringBuilder sb = new StringBuilder();
int previousIndex = 0;
int index = str.IndexOf(oldValue, comparison);
while (index != -1)
{
sb.Append(str.Substring(previousIndex, index - previousIndex));
sb.Append(newValue);
index += oldValue.Length;
previousIndex = index;
index = str.IndexOf(oldValue, index, comparison);
}
sb.Append(str.Substring(previousIndex));
return sb.ToString();
}
답변
질문의 제목이 실제로 요청되는 특정 질문보다 훨씬 크기 때문에 혼란스러운 답변 그룹입니다 . 읽은 후, 나는 여기에 모든 좋은 것들을 동화시키는 것에 대한 몇 가지 편집 내용이 있는지 확실하지 않으므로 요약하려고합니다.
여기에 언급 된 함정을 피하고 가장 광범위하게 적용 가능한 솔루션을 제공하는 확장 방법이 있습니다.
public static string ReplaceCaseInsensitiveFind(this string str, string findMe,
string newValue)
{
return Regex.Replace(str,
Regex.Escape(findMe),
Regex.Replace(newValue, "\\$[0-9]+", @"$$$0"),
RegexOptions.IgnoreCase);
}
그래서…
- 이것은 확장 방법 @MarkRobinson입니다
- 이것은 Regex @Helge 를 건너 뛰려고하지 않습니다 (Regex 외부 에서이 문자열을 스니핑하려면 실제로 바이트 단위로 수행해야합니다)
- @MichaelLiu의 패스 우수한 테스트 케이스를 ,
"œ".ReplaceCaseInsensitiveFind("oe", "")
그는 마음에 약간 다른 동작을했을 수 있지만.
불행히도, 세 가지 모두에 대한 @HA의 의견 Escape
은 정확하지 않습니다 . 초기 값이며 newValue
반드시 그럴 필요는 없습니다.
참고 : 그러나 “포착 된 값”마커 인 것의 일부인 경우$
삽입중인 새 값 에서을 이스케이프해야합니다 . 따라서 Regex.Replace [sic] 안에있는 Regex.Replace의 3 달러 기호. 그것 없이는 이와 같은 것이 깨집니다.
"This is HIS fork, hIs spoon, hissssssss knife.".ReplaceCaseInsensitiveFind("his", @"he$0r")
오류는 다음과 같습니다.
An unhandled exception of type 'System.ArgumentException' occurred in System.dll
Additional information: parsing "The\hisr\ is\ he\HISr\ fork,\ he\hIsr\ spoon,\ he\hisrsssssss\ knife\." - Unrecognized escape sequence \h.
Regex에 익숙한 사람들은 사용이 오류를 피하는 것처럼 느껴지지만, 여전히 스니핑 문자열 (부분적 으로 인코딩에서 Spolsky 를 읽은 후에 만)에서 부분적으로 당신이 무엇을 얻는 지 확실히 알 수 있습니다. 중요한 사용 사례를위한 것입니다. Crockford가 ” 안전하지 않은 정규식 “에 대해 조금 생각 나게합니다 . 너무 자주 우리는 우리가 원하는 것을 허용하는 $10
정규 표현식을 작성 하지만 (우리가 운이 좋으면) 의도하지 않게 더 많은 것을 허용합니다 (예를 들어 , 위의 newValue 정규 표현식에서 실제로 유효한 “캡처 값”문자열입니까?) . 두 방법 모두 가치가 있으며, 두 가지 방법 모두 서로 다른 유형의 의도하지 않은 오류를 권장합니다. 복잡성을 과소 평가하는 것은 종종 쉬운 일입니다.
그 이상한 $
탈출 (그리고 대체 가치에서 예상했던 Regex.Escape
것과 같은 캡처 된 가치 패턴을 피하지 못했습니다 $0
)은 잠시 동안 나를 화나게했습니다. 프로그래밍이 어렵다 (C) 1842
답변
확장 방법은 다음과 같습니다. 어디서 찾았는지 모르겠습니다.
public static class StringExtensions
{
public static string Replace(this string originalString, string oldValue, string newValue, StringComparison comparisonType)
{
int startIndex = 0;
while (true)
{
startIndex = originalString.IndexOf(oldValue, startIndex, comparisonType);
if (startIndex == -1)
break;
originalString = originalString.Substring(0, startIndex) + newValue + originalString.Substring(startIndex + oldValue.Length);
startIndex += newValue.Length;
}
return originalString;
}
}
답변
가장 쉬운 방법은 .Net과 함께 제공되며 .Net 1.0부터 사용 된 Replace 메서드를 사용하는 것입니다.
string res = Microsoft.VisualBasic.Strings.Replace(res,
"%PolicyAmount%",
"$0",
Compare: Microsoft.VisualBasic.CompareMethod.Text);
이 방법을 사용하려면 Microsoft.VisualBasic 어셈블리에 대한 참조를 추가해야합니다. 이 어셈블리는 .Net 런타임의 표준 부분으로, 추가 다운로드가 아니거나 더 이상 사용되지 않는 것으로 표시됩니다.
답변
/// <summary>
/// A case insenstive replace function.
/// </summary>
/// <param name="originalString">The string to examine.(HayStack)</param>
/// <param name="oldValue">The value to replace.(Needle)</param>
/// <param name="newValue">The new value to be inserted</param>
/// <returns>A string</returns>
public static string CaseInsenstiveReplace(string originalString, string oldValue, string newValue)
{
Regex regEx = new Regex(oldValue,
RegexOptions.IgnoreCase | RegexOptions.Multiline);
return regEx.Replace(originalString, newValue);
}
답변
cfeduke의 답변에서 영감을 얻어 IndexOf를 사용하여 문자열에서 이전 값을 찾은 다음 새 값으로 대체하는이 함수를 만들었습니다. 나는 이것을 수백만 행을 처리하는 SSIS 스크립트에서 사용했으며 정규식 방법은 이것보다 느립니다.
public static string ReplaceCaseInsensitive(this string str, string oldValue, string newValue)
{
int prevPos = 0;
string retval = str;
// find the first occurence of oldValue
int pos = retval.IndexOf(oldValue, StringComparison.InvariantCultureIgnoreCase);
while (pos > -1)
{
// remove oldValue from the string
retval = retval.Remove(pos, oldValue.Length);
// insert newValue in it's place
retval = retval.Insert(pos, newValue);
// check if oldValue is found further down
prevPos = pos + newValue.Length;
pos = retval.IndexOf(oldValue, prevPos, StringComparison.InvariantCultureIgnoreCase);
}
return retval;
}