Tôi có một chuỗi như:
"super exemple of string key : text I want to keep - end of my string"
Tôi muốn chỉ giữ chuỗi nằm giữa "key : "
và " - "
. Làm thế nào tôi có thể làm điều đó? Tôi phải sử dụng Regex hay tôi có thể làm theo cách khác?
Tôi có một chuỗi như:
"super exemple of string key : text I want to keep - end of my string"
Tôi muốn chỉ giữ chuỗi nằm giữa "key : "
và " - "
. Làm thế nào tôi có thể làm điều đó? Tôi phải sử dụng Regex hay tôi có thể làm theo cách khác?
Câu trả lời:
Có lẽ, một cách tốt chỉ là cắt bỏ một chuỗi con :
String St = "super exemple of string key : text I want to keep - end of my string";
int pFrom = St.IndexOf("key : ") + "key : ".Length;
int pTo = St.LastIndexOf(" - ");
String result = St.Substring(pFrom, pTo - pFrom);
string input = "super exemple of string key : text I want to keep - end of my string";
var match = Regex.Match(input, @"key : (.+?)-").Groups[1].Value;
hoặc chỉ với các hoạt động chuỗi
var start = input.IndexOf("key : ") + 6;
var match2 = input.Substring(start, input.IndexOf("-") - start);
Bạn có thể làm điều đó mà không cần regex
input.Split(new string[] {"key :"},StringSplitOptions.None)[1]
.Split('-')[0]
.Trim();
Tùy thuộc vào mức độ mạnh mẽ / linh hoạt mà bạn muốn triển khai của mình, điều này thực sự có thể hơi phức tạp. Đây là cách triển khai tôi sử dụng:
public static class StringExtensions {
/// <summary>
/// takes a substring between two anchor strings (or the end of the string if that anchor is null)
/// </summary>
/// <param name="this">a string</param>
/// <param name="from">an optional string to search after</param>
/// <param name="until">an optional string to search before</param>
/// <param name="comparison">an optional comparison for the search</param>
/// <returns>a substring based on the search</returns>
public static string Substring(this string @this, string from = null, string until = null, StringComparison comparison = StringComparison.InvariantCulture)
{
var fromLength = (from ?? string.Empty).Length;
var startIndex = !string.IsNullOrEmpty(from)
? @this.IndexOf(from, comparison) + fromLength
: 0;
if (startIndex < fromLength) { throw new ArgumentException("from: Failed to find an instance of the first anchor"); }
var endIndex = !string.IsNullOrEmpty(until)
? @this.IndexOf(until, startIndex, comparison)
: @this.Length;
if (endIndex < 0) { throw new ArgumentException("until: Failed to find an instance of the last anchor"); }
var subString = @this.Substring(startIndex, endIndex - startIndex);
return subString;
}
}
// usage:
var between = "a - to keep x more stuff".Substring(from: "-", until: "x");
// returns " to keep "
InvariantCulture
không hoạt động với Windows Universal Apps. Có cách nào để loại bỏ nó mà vẫn giữ nguyên chức năng của lớp của bạn không? @ChaseMedallion
Đây là cách tôi có thể làm điều đó
public string Between(string STR , string FirstString, string LastString)
{
string FinalString;
int Pos1 = STR.IndexOf(FirstString) + FirstString.Length;
int Pos2 = STR.IndexOf(LastString);
FinalString = STR.Substring(Pos1, Pos2 - Pos1);
return FinalString;
}
Tôi nghĩ điều này hoạt động:
static void Main(string[] args)
{
String text = "One=1,Two=2,ThreeFour=34";
Console.WriteLine(betweenStrings(text, "One=", ",")); // 1
Console.WriteLine(betweenStrings(text, "Two=", ",")); // 2
Console.WriteLine(betweenStrings(text, "ThreeFour=", "")); // 34
Console.ReadKey();
}
public static String betweenStrings(String text, String start, String end)
{
int p1 = text.IndexOf(start) + start.Length;
int p2 = text.IndexOf(end, p1);
if (end == "") return (text.Substring(p1));
else return text.Substring(p1, p2 - p1);
}
Regex ở đây quá mức cần thiết.
Bạn có thể sử dụng string.Split
với quá tải chiếm string[]
dấu phân cách nhưng điều đó cũng sẽ quá mức cần thiết.
Nhìn vào Substring
và IndexOf
- cái trước để lấy các phần của một chuỗi đã cho và chỉ mục và độ dài và cái thứ hai để tìm các chuỗi / ký tự bên trong được lập chỉ mục.
string.Split
.
Một giải pháp LINQ đang hoạt động:
string str = "super exemple of string key : text I want to keep - end of my string";
string res = new string(str.SkipWhile(c => c != ':')
.Skip(1)
.TakeWhile(c => c != '-')
.ToArray()).Trim();
Console.WriteLine(res); // text I want to keep
string str="super exemple of string key : text I want to keep - end of my string";
int startIndex = str.IndexOf("key") + "key".Length;
int endIndex = str.IndexOf("-");
string newString = str.Substring(startIndex, endIndex - startIndex);
Vì cái :
và cái -
là duy nhất bạn có thể sử dụng:
string input;
string output;
input = "super example of string key : text I want to keep - end of my string";
output = input.Split(new char[] { ':', '-' })[1];
hoặc, với một regex.
using System.Text.RegularExpressions;
...
var value =
Regex.Match(
"super exemple of string key : text I want to keep - end of my string",
"key : (.*) - ")
.Groups[1].Value;
với một ví dụ đang chạy .
Bạn có thể quyết định xem nó có quá mức cần thiết hay không.
như một phương thức tiện ích mở rộng đã được xác thực
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
var value =
"super exemple of string key : text I want to keep - end of my string"
.Between(
"key : ",
" - ");
Console.WriteLine(value);
}
}
public static class Ext
{
static string Between(this string source, string left, string right)
{
return Regex.Match(
source,
string.Format("{0}(.*){1}", left, right))
.Groups[1].Value;
}
}
Bạn có thể sử dụng phương thức mở rộng bên dưới:
public static string GetStringBetween(this string token, string first, string second)
{
if (!token.Contains(first)) return "";
var afterFirst = token.Split(new[] { first }, StringSplitOptions.None)[1];
if (!afterFirst.Contains(second)) return "";
var result = afterFirst.Split(new[] { second }, StringSplitOptions.None)[0];
return result;
}
Cách sử dụng là:
var token = "super exemple of string key : text I want to keep - end of my string";
var keyValue = token.GetStringBetween("key : ", " - ");
Tôi đã sử dụng đoạn mã từ Vijay Singh Rana về cơ bản thực hiện công việc. Nhưng nó gây ra vấn đề nếu firstString
không đã chứa lastString
. Những gì tôi muốn là trích xuất một access_token từ một JSON Response (không tải JSON Parser). Của tôi firstString
đã được \"access_token\": \"
và của tôi lastString
đã được \"
. Tôi đã kết thúc với một chút sửa đổi
string Between(string str, string firstString, string lastString)
{
int pos1 = str.IndexOf(firstString) + firstString.Length;
int pos2 = str.Substring(pos1).IndexOf(lastString);
return str.Substring(pos1, pos2);
}
Nếu bạn đang tìm kiếm giải pháp 1 dòng, thì đây là:
s.Substring(s.IndexOf("eT") + "eT".Length).Split("97".ToCharArray()).First()
Toàn bộ giải pháp 1 dòng, với System.Linq
:
using System;
using System.Linq;
class OneLiner
{
static void Main()
{
string s = "TextHereTisImortant973End"; //Between "eT" and "97"
Console.WriteLine(s.Substring(s.IndexOf("eT") + "eT".Length)
.Split("97".ToCharArray()).First());
}
}
Bạn đã có một số câu trả lời hay và tôi nhận thấy mã mà tôi đang cung cấp còn lâu mới hiệu quả và sạch sẽ nhất. Tuy nhiên, tôi nghĩ nó có thể hữu ích cho mục đích giáo dục. Chúng ta có thể sử dụng các lớp học và thư viện được tạo sẵn cả ngày. Nhưng nếu không hiểu được hoạt động bên trong, chúng ta chỉ bắt chước và lặp đi lặp lại và sẽ không bao giờ học được gì. Mã này hoạt động và cơ bản hoặc "trinh nguyên" hơn một số mã khác:
char startDelimiter = ':';
char endDelimiter = '-';
Boolean collect = false;
string parsedString = "";
foreach (char c in originalString)
{
if (c == startDelimiter)
collect = true;
if (c == endDelimiter)
collect = false;
if (collect == true && c != startDelimiter)
parsedString += c;
}
Bạn kết thúc với chuỗi mong muốn của bạn được gán cho biến parsedString. Hãy nhớ rằng nó cũng sẽ ghi lại các không gian tiếp tục và trước đó. Hãy nhớ rằng một chuỗi chỉ đơn giản là một mảng các ký tự có thể được thao tác giống như các mảng khác có chỉ số, v.v.
Bảo trọng.
Nếu bạn muốn xử lý nhiều lần xuất hiện của các cặp chuỗi con, sẽ không dễ dàng nếu không có RegEx:
Regex.Matches(input ?? String.Empty, "(?=key : )(.*)(?<= - )", RegexOptions.Singleline);
input ?? String.Empty
tránh đối số null ngoại lệ?=
giữ chuỗi con thứ nhất và?<=
giữ chuỗi con thứ haiRegexOptions.Singleline
cho phép dòng mới giữa cặp chuỗi con
Nếu thứ tự và số lần xuất hiện của các chuỗi con không quan trọng, thì một chuỗi nhanh và bẩn này có thể là một tùy chọn:
var parts = input?.Split(new string[] { "key : ", " - " }, StringSplitOptions.None);
string result = parts?.Length >= 3 ? result[1] : input;
Ít nhất nó tránh hầu hết các trường hợp ngoại lệ, bằng cách trả về chuỗi ban đầu nếu không có / chuỗi con nào phù hợp.
Như tôi luôn nói không có gì là không thể:
string value = "super exemple of string key : text I want to keep - end of my string";
Regex regex = new Regex(@"(key \: (.*?) _ )");
Match match = regex.Match(value);
if (match.Success)
{
Messagebox.Show(match.Value);
}
Hãy nhớ rằng sẽ thêm tham chiếu của System.Text.RegularExpressions
Hy vọng rằng tôi đã giúp.
Có lẽ như thế này
private static string Between(string text, string from, string to)
{
return text[(text.IndexOf(from)+from.Length)..text.IndexOf(to, text.IndexOf(from))];
}
Khi các câu hỏi được nêu dưới dạng một ví dụ duy nhất, sự mơ hồ chắc chắn sẽ xuất hiện. Câu hỏi này không phải là ngoại lệ.
Đối với ví dụ được đưa ra trong câu hỏi, chuỗi mong muốn là rõ ràng:
super example of string key : text I want to keep - end of my string
^^^^^^^^^^^^^^^^^^^
Tuy nhiên, chuỗi này chỉ là một ví dụ về chuỗi và chuỗi ranh giới mà các chuỗi con nhất định được xác định. Tôi sẽ xem xét một chuỗi chung với các chuỗi ranh giới chung, được biểu diễn như sau.
abc FF def PP ghi,PP jkl,FF mno PP pqr FF,stu FF vwx,PP yza
^^^^^^^^^^^^ ^^^^^
PP
là chuỗi trước , FF
là chuỗi sau và mũ bên cho biết chuỗi con nào sẽ được so khớp. (Trong ví dụ được đưa ra trong câu hỏi key :
là chuỗi đứng trước và -
là chuỗi sau.) Tôi đã giả định rằng PP
và FF
được đặt trước và theo sau bởi các ranh giới từ (sao cho PPA
và FF8
không khớp).
Các giả định của tôi, được phản ánh bởi những chiếc mũ bên, như sau:
PP
có thể đứng trước một (hoặc nhiều) FF
chuỗi con, nếu có, sẽ bị bỏ qua;PP
được theo sau bởi một hoặc nhiều PP
s trước khi FF
gặp phải, các PP
s sau đây là một phần của chuỗi con giữa các chuỗi trước và sau;PP
được theo sau bởi một hoặc nhiều FF
s trước khi PP
gặp phải, chuỗi FF
sau đầu tiên PP
được coi là chuỗi sau.Lưu ý rằng nhiều câu trả lời ở đây chỉ giải quyết các chuỗi của biểu mẫu
abc PP def FF ghi
^^^^^
hoặc là
abc PP def FF ghi PP jkl FF mno
^^^^^ ^^^^^
Người ta có thể sử dụng một biểu thức chính quy, các cấu trúc mã hoặc kết hợp cả hai để xác định các chuỗi con quan tâm. Tôi không đưa ra đánh giá về cách tiếp cận nào là tốt nhất. Tôi sẽ chỉ trình bày biểu thức chính quy sau đây sẽ khớp với các chuỗi con được quan tâm.
(?<=\bPP\b)(?:(?!\bFF\b).)*(?=\bFF\b)
Tôi đã thử nghiệm điều này với công cụ regex PCRE (PHP), nhưng vì regex không có gì kỳ lạ, tôi chắc chắn rằng nó sẽ hoạt động với công cụ regex .NET (rất mạnh mẽ).
Công cụ regex thực hiện các hoạt động sau:
(?<= : begin a positive lookbehind
\bPP\b : match 'PP'
) : end positive lookbehind
(?: : begin a non-capture group
(?! : begin a negative lookahead
\bFF\b : match 'FF'
) : end negative lookahead
. : match any character
) : end non-capture group
* : execute non-capture group 0+ times
(?= : begin positive lookahead
\bFF\b : match 'FF'
) : end positive lookahead
Kỹ thuật này, khớp một ký tự tại một thời điểm, theo sau chuỗi trước, cho đến khi ký tự đó F
và được theo sau bởi F
(hoặc nói chung, ký tự tạo thành chuỗi tạo thành chuỗi sau), được gọi là Giải pháp Mã thông báo Tham lam .
Đương nhiên, regex sẽ phải được sửa đổi (nếu có thể) nếu các giả định tôi đặt ra ở trên bị thay đổi.
1. Di chuyển con trỏ xung quanh để xem giải thích chi tiết.
Trong C # 8.0 trở lên, bạn có thể sử dụng toán tử phạm vi ..
như trong
var s = "header-THE_TARGET_STRING.7z";
var from = s.IndexOf("-") + "-".Length;
var to = s.IndexOf(".7z");
var versionString = s[from..to]; // THE_TARGET_STRING
Xem tài liệu để biết chi tiết.
substring
vàindexof