Ví dụ, regex này
(.*)<FooBar>
sẽ phù hợp:
abcde<FooBar>
Nhưng làm thế nào để tôi có được nó phù hợp trên nhiều dòng?
abcde
fghij<FooBar>
Ví dụ, regex này
(.*)<FooBar>
sẽ phù hợp:
abcde<FooBar>
Nhưng làm thế nào để tôi có được nó phù hợp trên nhiều dòng?
abcde
fghij<FooBar>
Câu trả lời:
Nó phụ thuộc vào ngôn ngữ, nhưng cần có một công cụ sửa đổi mà bạn có thể thêm vào mẫu biểu thức chính quy. Trong PHP nó là:
/(.*)<FooBar>/s
Các s ở cuối làm cho dấu chấm khớp với tất cả các ký tự bao gồm cả dòng mới.
s
sửa đổi. Thay vào đó, làm [^]*
cho hiệu quả tương tự.
m
sửa đổi
Thử cái này:
((.|\n)*)<FooBar>
Về cơ bản, nó nói "bất kỳ ký tự hoặc một dòng mới" lặp đi lặp lại từ 0 lần trở lên.
((.|\n|\r)*)<FooBar>
[\s\S]*
hoặc (?s).*
.
Câu hỏi là, .
mô hình có thể phù hợp với bất kỳ nhân vật? Câu trả lời khác nhau từ động cơ đến động cơ. Sự khác biệt chính là liệu mẫu được sử dụng bởi thư viện regex POSIX hay không POSIX.
Lưu ý đặc biệt về mô hình lua: chúng không được coi là biểu thức chính quy, nhưng .
khớp với bất kỳ char nào ở đó, giống như các công cụ dựa trên POSIX.
Một lưu ý khác về chiếu và quãng tám: .
phù hợp với bất kỳ char theo mặc định ( demo ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');
( tokens
chứa một abcde\n fghij
mục).
Ngoài ra, trong tất cả các tăngTheo mặc định, ngữ pháp regex của dấu chấm khớp với ngắt dòng theo mặc định. Ngữ pháp ECMAScript của Boost cho phép bạn tắt tính năng này bằng regex_constants::no_mod_m
( nguồn ).
Đối với nhà tiên tri(dựa trên POSIX), sử dụng n
tùy chọn ( bản demo ):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
Động cơ dựa trên POSIX :
Chỉ đơn giản là .
đã khớp dòng ngắt, không cần sử dụng bất kỳ sửa đổi nào, xembash( bản demo ).
Các tcl( bản demo ),postgresql( bản demo ),r(TRE, cơ sở R engine mặc định không có perl=TRUE
, đối với cơ sở R với perl=TRUE
hoặc cho stringr / stringi mẫu, sử dụng (?s)
modifier inline) ( bản demo ) cũng đối xử .
theo cùng một cách.
Tuy nhiên , hầu hết các công cụ dựa trên POSIX xử lý từng dòng đầu vào. Do đó, .
không khớp với các ngắt dòng chỉ vì chúng không nằm trong phạm vi. Dưới đây là một số ví dụ về cách ghi đè này:
sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'
( H;1h;$!d;x;
nhét tệp vào bộ nhớ). Nếu phải bao gồm toàn bộ các dòng, sed '/start_pattern/,/end_pattern/d' file
(loại bỏ khỏi bắt đầu sẽ kết thúc với các dòng phù hợp được bao gồm) hoặc sed '/start_pattern/,/end_pattern/{{//!d;};}' file
(với các dòng phù hợp được loại trừ) có thể được xem xét.perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"
( -0
nhét toàn bộ tệp vào bộ nhớ, -p
in tệp sau khi áp dụng tập lệnh được cung cấp bởi -e
). Lưu ý rằng việc sử dụng -000pe
sẽ làm mờ tệp và kích hoạt mode chế độ đoạn 'trong đó Perl sử dụng các dòng mới liên tiếp ( \n\n
) làm dấu tách bản ghi.grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file
. Ở đây, z
cho phép ẩn tệp, (?s)
bật chế độ DOTALL cho .
mẫu, bật (?i)
chế độ không phân biệt chữ hoa chữ thường, \K
bỏ qua văn bản khớp cho đến nay, *?
là một bộ định lượng lười biếng, (?=<Foobar>)
khớp với vị trí trước đó <Foobar>
.pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file
( M
cho phép tập tin ở đây). Lưu ý pcregrep
là một giải pháp tốt cho grep
người dùng Mac OS .Động cơ không dựa trên POSIX :
s
sửa đổi PCRE_DOTALL : preg_match('~(.*)<Foobar>~s', $s, $m)
( bản demo )RegexOptions.Singleline
cờ ( bản demo ): var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
(?s)
tùy chọn nội tuyến:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
s
sửa đổi (hoặc (?s)
phiên bản nội tuyến khi bắt đầu) ( bản demo ):/(.*)<FooBar>/s
re.DOTALL
(hoặc re.S
) cờ hoặc công cụ (?s)
sửa đổi nội tuyến ( bản demo ): m = re.search(r"(.*)<FooBar>", s, flags=re.S)
(và sau đó if m:
, print(m.group(1))
)Pattern.DOTALL
sửa đổi (hoặc (?s)
cờ nội tuyến ) ( bản demo ):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
(?s)
công cụ sửa đổi trong mẫu ( bản demo ):regex = /(?s)(.*)<FooBar>/
(?s)
sửa đổi ( bản demo ):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
[^]
hoặc giải pháp [\d\D]
/ [\w\W]
/ [\s\S]
( bản demo ):s.match(/([\s\S]*)<FooBar>/)[1]
std::regex
) Sử dụng [\s\S]
hoặc cách giải quyết của JS ( bản demo ):regex rex(R"(([\s\S]*)<FooBar>)");
vba bản thảo- Sử dụng cách tiếp cận tương tự như trong JavaScript , ([\s\S]*)<Foobar>
. ( LƯU Ý : MultiLine
Thuộc tính của
RegExp
đối tượng đôi khi bị nhầm là tùy chọn cho phép .
khớp giữa các ngắt dòng, trong khi thực tế, nó chỉ thay đổi hành vi ^
và $
hành vi để khớp với bắt đầu / kết thúc của dòng chứ không phải trong chuỗi regex ) hành vi.)
hồng ngọc- Sử dụng công cụ sửa đổi /m
MULTILINE ( bản demo ):s[/(.*)<Foobar>/m, 1]
(?s)
: regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]
( bản demo )stringr
/ stringi
regex được cung cấp bởi công cụ regex ICU, cũng sử dụng (?s)
: stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]
( bản demo )(?s)
khi bắt đầu ( bản demo ):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
dotMatchesLineSeparators
hoặc (dễ dàng hơn) chuyển công cụ (?s)
sửa đổi nội tuyến cho mẫu:let rx = "(?s)(.*)<Foobar>"
(?s)
hoạt động dễ nhất, nhưng đây là cách tùy chọn có thể được sử dụng :NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators error:®exError];
(?s)
sửa đổi ( bản demo ): "(?s)(.*)<Foobar>"
(trong Bảng tính Google, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")
)GHI CHÚ(?s)
:
Trong hầu hết các công cụ không phải POSIX, công cụ (?s)
sửa đổi nội tuyến (hoặc tùy chọn cờ nhúng) có thể được sử dụng để thực thi .
để khớp dòng ngắt.
Nếu được đặt ở đầu mẫu, (?s)
thay đổi giá trị của tất cả .
trong mẫu. Nếu cái (?s)
được đặt ở đâu đó sau khi bắt đầu, chỉ những cái đó .
sẽ bị ảnh hưởng nằm ở bên phải của nó trừ khi đây là mẫu được truyền cho Python re
. Trong Python re
, bất kể (?s)
vị trí, toàn bộ mô hình .
đều bị ảnh hưởng. Các (?s)
hiệu ứng được ngừng sử dụng (?-s)
. Một nhóm được sửa đổi có thể được sử dụng để chỉ ảnh hưởng đến một phạm vi xác định của mẫu biểu thức chính quy (ví dụ: Delim1(?s:.*?)\nDelim2.*
sẽ tạo .*?
kết quả khớp đầu tiên trên các dòng mới và nhóm thứ hai .*
sẽ chỉ khớp với phần còn lại của dòng).
Lưu ý POSIX :
Trong các công cụ regex không POSIX, để phù hợp với bất kỳ cấu trúc char, [\s\S]
/ [\d\D]
/ [\w\W]
có thể được sử dụng.
Trong POSIX, [\s\S]
không khớp với bất kỳ char nào (như trong JavaScript hoặc bất kỳ công cụ không phải POSIX nào) vì các chuỗi thoát regex không được hỗ trợ bên trong các biểu thức ngoặc. [\s\S]
được phân tích cú pháp dưới dạng biểu thức ngoặc khớp với một char \
hoặc s
hoặc S
.
#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m
cho các cờ regex của họ để phản ánh điều đó. Và arbitor luôn là công cụ sửa đổi nội tuyến. Nơi (?-sm)(?s).*
đặt lại.
.
phù hợp với bất kỳ char nào ở đó (bao gồm cả ngắt dòng). Xem bản demo Bash trực tuyến này .
Go
trong câu trả lời!
Nếu bạn đang sử dụng tìm kiếm Eclipse, bạn có thể kích hoạt tùy chọn "DOTALL" để tạo '.' khớp với bất kỳ ký tự nào, kể cả các dấu phân cách dòng: chỉ cần thêm "(? s)" vào đầu chuỗi tìm kiếm của bạn. Thí dụ:
(?s).*<FooBar>
(?s)
=>(?m)
Trong nhiều phương ngữ regex, /[\S\s]*<Foobar>/
sẽ làm những gì bạn muốn. Nguồn
([\s\S]*)<FooBar>
Dấu chấm khớp với tất cả ngoại trừ dòng mới (\ r \ n). Vì vậy, sử dụng \ s \ S, sẽ khớp với TẤT CẢ các ký tự.
[text rangeOfString:regEx options:NSRegularExpressionSearch]
. Cảm ơn!
<FooBar>
chúng ta cũng có thể sử dụng
(.*?\n)*?
để phù hợp với tất cả mọi thứ bao gồm cả dòng mới mà không tham lam
Điều này sẽ làm cho dòng mới tùy chọn
(.*?|\n)*?
"."
thông thường không khớp dòng ngắt. Hầu hết các công cụ regex cho phép bạn thêm S
-flag (còn được gọi DOTALL
và SINGLELINE
) để tạo ra các "."
dòng mới. Nếu thất bại, bạn có thể làm một cái gì đó như [\S\s]
.
/(.*)<FooBar>/s
các nguyên nhân khiến Dot (.) khớp với lợi nhuận vận chuyển
s
cờ tồn tại trong PCRE, công cụ hoàn chỉnh nhất (có sẵn trong Perl và PHP). PCRE có 10 cờ (và rất nhiều tính năng khác) trong khi JavaScript chỉ có 3 cờ ( gmi
).
Trong biểu thức chính quy dựa trên java, bạn có thể sử dụng [\s\S]
s
cờ vào mẫu trong Java và JavaScript không có s
cờ.
Sử dụng công cụ sửa đổi mẫu sU sẽ có được kết quả khớp mong muốn trong PHP.
preg_match('/(.*)/sU',$content,$match);
http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.potype.modifier.php
Trong ngữ cảnh sử dụng trong các ngôn ngữ, các biểu thức chính quy hoạt động trên các chuỗi, không phải các dòng. Vì vậy, bạn sẽ có thể sử dụng regex bình thường, giả sử rằng chuỗi đầu vào có nhiều dòng.
Trong trường hợp này, regex đã cho sẽ khớp với toàn bộ chuỗi, vì "<FooBar>" có mặt. Tùy thuộc vào chi tiết cụ thể của việc triển khai regex, giá trị $ 1 (thu được từ "(. *)") Sẽ là "fghij" hoặc "abcde \ nfghij". Như những người khác đã nói, một số triển khai cho phép bạn kiểm soát xem "." sẽ phù hợp với dòng mới, cho bạn sự lựa chọn.
Việc sử dụng biểu thức chính quy dựa trên dòng thường dành cho những thứ dòng lệnh như egrep.
Tôi đã có cùng một vấn đề và giải quyết nó có thể không phải là cách tốt nhất nhưng nó hoạt động. Tôi đã thay thế tất cả các ngắt dòng trước khi tôi thực hiện trận đấu thực sự của mình:
mystring= Regex.Replace(mystring, "\r\n", "")
Tôi đang thao túng HTML để ngắt dòng không thực sự quan trọng với tôi trong trường hợp này.
Tôi đã thử tất cả các đề xuất ở trên mà không gặp may, tôi đang sử dụng .Net 3.5 FYI
(\s|\S)
dường như cũng đang lừa tôi!
(?s)
để tạo .
bất kỳ ký tự nào. Không sử dụng (\s|\S)
sẽ làm chậm hiệu suất.
Trong Javascript, bạn có thể sử dụng [^] * để tìm kiếm các ký tự từ 0 đến vô hạn, bao gồm cả ngắt dòng.
$("#find_and_replace").click(function() {
var text = $("#textarea").val();
search_term = new RegExp("[^]*<Foobar>", "gi");;
replace_term = "Replacement term";
var new_text = text.replace(search_term, replace_term);
$("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij<Foobar></textarea>
nói chung là . không khớp với dòng mới, vì vậy hãy thử((.|\n)*)<foobar>
\r
.:((?:.|\r?\n)*)<foobar>
Thông thường chúng ta phải sửa đổi một chuỗi con với một vài từ khóa trải đều trên các dòng trước chuỗi con. Hãy xem xét một yếu tố xml:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
Giả sử chúng ta muốn sửa đổi 81, thành một số giá trị khác, giả sử 40. Trước tiên .UID.21..UID.
, xác định , sau đó bỏ qua tất cả các ký tự bao gồm \n
đến .PercentCompleted.
. Mẫu biểu thức chính quy và đặc tả thay thế là:
String hw = new String("<TASK>\n <UID>21</UID>\n <Name>Architectural design</Name>\n <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.
String iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>40</PercentComplete>
</TASK>
Nhóm con (.|\n)
có lẽ là nhóm mất tích $3
. Nếu chúng ta làm cho nó không bị bắt bởi (?:.|\n)
thì đó $3
là (<PercentComplete>)
. Vì vậy, mô hình và replaceSpec
cũng có thể là:
pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")
và thay thế hoạt động chính xác như trước.
Thông thường tìm kiếm ba dòng liên tiếp trong Powershell, nó sẽ trông như sau:
$file = get-content file.txt -raw
$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n' # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n' # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n' # both
$file -match $pattern
# output
True
Kỳ lạ thay, đây sẽ là văn bản unix tại dấu nhắc, nhưng văn bản windows trong một tệp:
$pattern = 'lineone
linetwo
linethree
'
Đây là một cách để in ra các kết thúc dòng:
'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'
# output
lineone\nlinetwo\nlinethree\n
Một cách sẽ là sử dụng s
cờ (giống như câu trả lời được chấp nhận):
/(.*)<FooBar>/s
Cách thứ hai sẽ là sử dụng m
cờ (multiline) và bất kỳ mẫu nào sau đây:
/([\s\S]*)<FooBar>/m
hoặc là
/([\d\D]*)<FooBar>/m
hoặc là
/([\w\W]*)<FooBar>/m
jex.im hình dung các biểu thức thông thường: