Cách trích xuất một chuỗi con bằng regex


382

Tôi có một chuỗi có hai dấu ngoặc đơn trong đó, 'ký tự. Ở giữa các dấu ngoặc đơn là dữ liệu tôi muốn.

Làm cách nào tôi có thể viết regex để trích xuất "dữ liệu tôi muốn" từ văn bản sau?

mydata = "some string with 'the data i want' inside";

Câu trả lời:


569

Giả sử bạn muốn phần giữa các dấu ngoặc đơn, hãy sử dụng biểu thức chính quy này với Matcher:

"'(.*?)'"

Thí dụ:

String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
    System.out.println(matcher.group(1));
}

Kết quả:

dữ liệu tôi muốn

12
chết tiệt .. tôi luôn quên về công cụ sửa đổi không tham lam :(
Mihai Toader

33
thay thế "nếu" bằng "trong khi" khi bạn mong đợi nhiều hơn một lần xuất hiện
OneWorld

14
lưu ý rằng matcher.find () là cần thiết để mẫu mã này hoạt động. không gọi phương thức này sẽ dẫn đến ngoại lệ "Không tìm thấy kết quả khớp" khi matcher.group (1) được gọi.
rexford

25
Nhóm @mFontoura (0) sẽ trả lại kết quả khớp hoàn chỉnh với bên ngoài ''. nhóm (1) trả về những gì ở giữa '' mà không có ''.
tagy22

6
@Larry đây là một trả lời muộn, nhưng? trong trường hợp này là công cụ sửa đổi không tham lam, do đó, this 'is' my 'data' with quotesnó sẽ dừng sớm và quay lại isthay vì khớp càng nhiều ký tự càng tốt và trả về is' my 'data, đó là hành vi mặc định.
Máy chấm công

68

Bạn không cần regex cho việc này.

Thêm apache commons lang vào dự án của bạn ( http://commons.apache.org/proper/commons-lang/ ), sau đó sử dụng:

String dataYouWant = StringUtils.substringBetween(mydata, "'");

12
Bạn phải tính đến việc phần mềm của bạn sẽ được phân phối như thế nào. Nếu đó là một cái gì đó giống như một webstart, thì không nên chỉ thêm commons Apache để sử dụng chức năng này. Nhưng có lẽ không phải vậy. Bên cạnh đó, commons Apache còn rất nhiều thứ khác. Ngay cả khó khăn khi biết regex, bạn phải cẩn thận khi sử dụng nó. Regex có thể rất khó đọc, viết và gỡ lỗi. Đưa ra một số bối cảnh sử dụng điều này có thể là giải pháp tốt hơn.
Beothorn

3
Đôi khi StringUtils đã có sẵn, trong những trường hợp đó, giải pháp này sạch sẽ và dễ đọc hơn nhiều.
Gábor Nagy

7
Nó giống như mua một chiếc xe để đi 5 dặm (khi bạn đang đi du lịch chỉ một lần trong một năm).
nguyện

Trong khi chuỗi con tìm kiếm một chuỗi hoặc giá trị cụ thể, regex tìm định dạng. Nó ngày càng năng động hơn. Bạn cần regex, nếu bạn đang tìm kiếm một mẫu thay vì một giá trị đặc biệt.
burakhan alkan

14
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(".*'([^']*)'.*");
        String mydata = "some string with 'the data i want' inside";

        Matcher matcher = pattern.matcher(mydata);
        if(matcher.matches()) {
            System.out.println(matcher.group(1));
        }

    }
}

2
System.out.println (matcher.group (0)); <--- Chỉ số dựa trên số không
nclord

4
Nhóm số (0) có ý nghĩa đặc biệt, các nhóm bắt đầu bắt đầu ở nhóm chỉ số (1) (tức là nhóm (1) là chính xác trong câu trả lời). "Các nhóm bắt giữ được lập chỉ mục từ trái sang phải, bắt đầu từ một. Nhóm 0 biểu thị toàn bộ mẫu" - Nguồn: docs.oracle.com/javase/8/docs/api/java/util/regex/ trộm
Apriori

12

Có một lớp lót đơn giản cho việc này:

String target = myData.replaceAll("[^']*(?:'(.*?)')?.*", "$1");

Bằng cách làm cho nhóm phù hợp tùy chọn, điều này cũng phục vụ cho các trích dẫn không được tìm thấy bằng cách trả lại một khoảng trống trong trường hợp đó.

Xem bản demo trực tiếp .


10

Bởi vì bạn cũng đánh dấu Scala, một giải pháp không có biểu thức chính quy dễ dàng xử lý nhiều chuỗi trích dẫn:

val text = "some string with 'the data i want' inside 'and even more data'"
text.split("'").zipWithIndex.filter(_._2 % 2 != 0).map(_._1)

res: Array[java.lang.String] = Array(the data i want, and even more data)

4
Vì vậy, giải pháp dễ đọc, đó là lý do tại sao mọi người yêu thích scala Tôi tin rằng :)
nguyện

3
Tại sao không chỉ .split('\'').get(2)hoặc một cái gì đó đến mức đó trong Java? Tôi nghĩ rằng bạn có thể cần phải quét não nếu bạn nghĩ đó là một giải pháp dễ đọc - có vẻ như ai đó đang cố gắng thực hiện một số môn đánh gôn với tôi.
ArtOfWarfare


4

như trong javascript:

mydata.match(/'([^']+)'/)[1]

regrec thực tế là: /'([^']+)'/

nếu bạn sử dụng công cụ sửa đổi không tham lam (theo bài đăng khác) thì nó sẽ như thế này:

mydata.match(/'(.*?)'/)[1]

nó sạch hơn


2

Ở Scala,

val ticks = "'([^']*)'".r

ticks findFirstIn mydata match {
    case Some(ticks(inside)) => println(inside)
    case _ => println("nothing")
}

for (ticks(inside) <- ticks findAllIn mydata) println(inside) // multiple matches

val Some(ticks(inside)) = ticks findFirstIn mydata // may throw exception

val ticks = ".*'([^']*)'.*".r    
val ticks(inside) = mydata // safe, shorter, only gets the first set of ticks


1

Apache Commons Lang cung cấp một loạt các tiện ích trợ giúp cho API java.lang, đáng chú ý nhất là các phương thức thao tác Chuỗi. Trong trường hợp của bạn, các chuỗi con bắt đầu và kết thúc là như nhau, vì vậy chỉ cần gọi hàm sau.

StringUtils.substringBetween(String str, String tag)

Lấy Chuỗi được lồng vào giữa hai trường hợp của cùng một Chuỗi .

Nếu các điểm bắt đầu và kết thúc khác nhau thì sử dụng phương pháp quá tải sau đây.

StringUtils.substringBetween(String str, String open, String close)

Lấy chuỗi được lồng vào giữa hai chuỗi.

Nếu bạn muốn tất cả các trường hợp của các chuỗi con phù hợp, sau đó sử dụng,

StringUtils.substringsBetween(String str, String open, String close)

Tìm kiếm Chuỗi cho các chuỗi con được phân tách bằng thẻ bắt đầu và kết thúc, trả về tất cả các chuỗi con phù hợp trong một mảng .

Ví dụ trong câu hỏi để có được tất cả các phiên bản của chuỗi con phù hợp

String[] results = StringUtils.substringsBetween(mydata, "'", "'");

0

bạn có thể sử dụng cái này tôi sử dụng vòng lặp while để lưu trữ tất cả các chuỗi con phù hợp trong mảng nếu bạn sử dụng

if (matcher.find()) { System.out.println(matcher.group(1)); }

bạn sẽ có được chuỗi con phù hợp để bạn có thể sử dụng chuỗi này để có được tất cả chuỗi con phù hợp

Matcher m = Pattern.compile("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+").matcher(text);
   // Matcher  mat = pattern.matcher(text);
    ArrayList<String>matchesEmail = new ArrayList<>();
        while (m.find()){
            String s = m.group();
            if(!matchesEmail.contains(s))
                matchesEmail.add(s);
        }

    Log.d(TAG, "emails: "+matchesEmail);

0

thêm phụ thuộc apache.commons vào pom.xml của bạn

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>

Và dưới đây mã hoạt động.

StringUtils.substringBetween(String mydata, String "'", String "'")

0

Một số cách nhóm (1) không làm việc cho tôi. Tôi đã sử dụng nhóm (0) để tìm phiên bản url.

Pattern urlVersionPattern = Pattern.compile("\\/v[0-9][a-z]{0,1}\\/");
Matcher m = urlVersionPattern.matcher(url);
if (m.find()) { 
    return StringUtils.substringBetween(m.group(0), "/", "/");
}
return "v0";
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.