여러 줄로 된 줄을 어떻게 줄로 나눕니 까?
나도 알아
var result = input.Split("\n\r".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
조금 못 생겼고 빈 줄을 잃습니다. 더 나은 해결책이 있습니까?
여러 줄로 된 줄을 어떻게 줄로 나눕니 까?
나도 알아
var result = input.Split("\n\r".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
조금 못 생겼고 빈 줄을 잃습니다. 더 나은 해결책이 있습니까?
답변:
보기 흉한 경우 불필요한 ToCharArray
통화를 제거하십시오 .
\n
또는 로 나누려면 \r
두 가지 옵션이 있습니다.
배열 리터럴을 사용하십시오. 그러나 이것은 Windows 스타일 줄 끝을위한 빈 줄을 제공합니다 \r\n
.
var result = text.Split(new [] { '\r', '\n' });
Bart가 나타내는 정규식을 사용하십시오.
var result = Regex.Split(text, "\r\n|\r|\n");
빈 줄을 유지하려면 왜 C #에 명시 적으로 버리라고 지시합니까? ( StringSplitOptions
parameter) – StringSplitOptions.None
대신 사용하십시오.
Environment.NewLine
내가 생각하는 한 계속 진행됩니다. 실제로 가능한 모든 솔루션 중에서 정규식을 사용하는 솔루션을 선호합니다. 왜냐하면 모든 소스 플랫폼을 올바르게 처리하기 때문입니다.
StringSplitOptions.RemoveEmptyEntries
.
이것은 훌륭하게 작동하며 Regex보다 빠릅니다.
input.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None)
"\r\n"
한 줄 바꿈으로 사용되도록 배열에서 첫 번째 를 갖는 것이 중요합니다 . 위의 Regex 솔루션 중 하나와 동일한 결과를 제공합니다.
Regex.Split(input, "\r\n|\r|\n")
Regex.Split(input, "\r?\n|\r")
Regex가 약 10 배 느리다는 것을 제외하고. 내 테스트는 다음과 같습니다.
Action<Action> measure = (Action func) => {
var start = DateTime.Now;
for (int i = 0; i < 100000; i++) {
func();
}
var duration = DateTime.Now - start;
Console.WriteLine(duration);
};
var input = "";
for (int i = 0; i < 100; i++)
{
input += "1 \r2\r\n3\n4\n\r5 \r\n\r\n 6\r7\r 8\r\n";
}
measure(() =>
input.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None)
);
measure(() =>
Regex.Split(input, "\r\n|\r|\n")
);
measure(() =>
Regex.Split(input, "\r?\n|\r")
);
산출:
00 : 00 : 03.8527616
00 : 00 : 31.8017726
00 : 00 : 32.5557128
확장 방법은 다음 과 같습니다 .
public static class StringExtensionMethods
{
public static IEnumerable<string> GetLines(this string str, bool removeEmptyLines = false)
{
return str.Split(new[] { "\r\n", "\r", "\n" },
removeEmptyLines ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);
}
}
용법:
input.GetLines() // keeps empty lines
input.GetLines(true) // removes empty lines
[\r\n]{1,2}
\n\r
않거나 \n\n
한 줄 바꿈으로 잘못되었습니다.
Hello\n\nworld\n\n
에지 케이스는 어떻습니까? 텍스트가있는 한 줄, 빈 줄, 텍스트가있는 다른 줄, 빈 줄이 있습니다.
Regex.Split을 사용할 수 있습니다.
string[] tokens = Regex.Split(input, @"\r?\n|\r");
편집 : |\r
(이전) Mac 라인 터미네이터를 설명하기 위해 추가되었습니다 .
\r
에서는 줄 끝으로 만 사용되므로 작동하지 않습니다 .
빈 줄을 유지하려면 StringSplitOptions를 제거하십시오.
var result = input.Split(System.Environment.NewLine.ToCharArray());
나는이 있었다 다른 대답 잭의 기반으로하지만,이 한 대답을 , 훨씬 빠르게되고 는 비동기 적으로 작동하기 때문에 비록 약간 느린 선호 될 수 있습니다.
public static class StringExtensionMethods
{
public static IEnumerable<string> GetLines(this string str, bool removeEmptyLines = false)
{
using (var sr = new StringReader(str))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (removeEmptyLines && String.IsNullOrWhiteSpace(line))
{
continue;
}
yield return line;
}
}
}
}
용법:
input.GetLines() // keeps empty lines
input.GetLines(true) // removes empty lines
테스트:
Action<Action> measure = (Action func) =>
{
var start = DateTime.Now;
for (int i = 0; i < 100000; i++)
{
func();
}
var duration = DateTime.Now - start;
Console.WriteLine(duration);
};
var input = "";
for (int i = 0; i < 100; i++)
{
input += "1 \r2\r\n3\n4\n\r5 \r\n\r\n 6\r7\r 8\r\n";
}
measure(() =>
input.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)
);
measure(() =>
input.GetLines()
);
measure(() =>
input.GetLines().ToList()
);
산출:
00 : 00 : 03.9603894
00 : 00 : 00.0029996
00 : 00 : 04.8221971
약간 비틀었지만 반복 블록은 다음과 같습니다.
public static IEnumerable<string> Lines(this string Text)
{
int cIndex = 0;
int nIndex;
while ((nIndex = Text.IndexOf(Environment.NewLine, cIndex + 1)) != -1)
{
int sIndex = (cIndex == 0 ? 0 : cIndex + 1);
yield return Text.Substring(sIndex, nIndex - sIndex);
cIndex = nIndex;
}
yield return Text.Substring(cIndex + 1);
}
그런 다음 전화를 걸 수 있습니다.
var result = input.Lines().ToArray();
private string[] GetLines(string text)
{
List<string> lines = new List<string>();
using (MemoryStream ms = new MemoryStream())
{
StreamWriter sw = new StreamWriter(ms);
sw.Write(text);
sw.Flush();
ms.Position = 0;
string line;
using (StreamReader sr = new StreamReader(ms))
{
while ((line = sr.ReadLine()) != null)
{
lines.Add(line);
}
}
sw.Close();
}
return lines.ToArray();
}
혼합 줄 끝을 올바르게 처리하는 것은 까다 롭습니다 . 우리가 알다시피, 라인 종료 문자가 "줄 바꿈"할 수있다 (ASCII 10, \n
, \x0A
, \u000A
), "캐리지 리턴"(ASCII 13, \r
, \x0D
, \u000D
), 또는 이들의 조합. DOS로 돌아 가면 Windows는 두 문자 시퀀스 CR-LF를 사용하므로이 \u000D\u000A
조합은 한 줄만 방출해야합니다. 유닉스는 단일을 사용 \u000A
하고 아주 오래된 맥은 단일 \u000D
문자를 사용했습니다 . 단일 텍스트 파일 내에서 이러한 문자의 임의 혼합을 처리하는 표준 방법은 다음과 같습니다.
\u000D\u000A
)는 다음 두 가지가 함께 하나의 광고를 건너.String.Empty
행을 리턴하지 않는 유일한 입력입니다 (모든 문자는 하나 이상의 행을 수반 함)위의 규칙은 StringReader.ReadLine 의 동작 및 관련 함수를 설명하며 아래에 표시된 함수는 동일한 결과를 생성합니다. CR / LF의 임의의 시퀀스 또는 조합을 올바르게 처리하기 위해 이러한 지침을 충실하게 구현 하는 효율적인 C # 줄 바꿈 기능입니다. 열거 된 줄에는 CR / LF 문자가 포함되지 않습니다. 빈 라인은 보존로 반환됩니다 String.Empty
.
/// <summary>
/// Enumerates the text lines from the string.
/// ⁃ Mixed CR-LF scenarios are handled correctly
/// ⁃ String.Empty is returned for each empty line
/// ⁃ No returned string ever contains CR or LF
/// </summary>
public static IEnumerable<String> Lines(this String s)
{
int j = 0, c, i;
char ch;
if ((c = s.Length) > 0)
do
{
for (i = j; (ch = s[j]) != '\r' && ch != '\n' && ++j < c;)
;
yield return s.Substring(i, j - i);
}
while (++j < c && (ch != '\r' || s[j] != '\n' || ++j < c));
}
참고 : StringReader
각 호출에서 인스턴스를 만드는 오버 헤드가 마음에 들지 않으면 다음 C # 7 코드를 대신 사용할 수 있습니다 . 언급 한 바와 같이, 위의 예는 약간 더 효율적일 수 있지만,이 두 함수는 모두 동일한 결과를 생성합니다.
public static IEnumerable<String> Lines(this String s)
{
using (var tr = new StringReader(s))
while (tr.ReadLine() is String L)
yield return L;
}