Como faço para combinar algum personagem em várias linhas em uma expressão regular?
Pergunta
Por exemplo, este regex
(.*)<FooBar>
vai corresponder:
abcde<FooBar>
Mas como faço para combinar com várias linhas?
abcde
fghij<FooBar>
Solução
Depende do idioma, mas deve haver um modificador que você pode adicionar ao padrão Regex. No PHP é:
/(.*)<FooBar>/s
o s No final, faz com que o ponto corresponda tudo Personagens, incluindo novas linhas.
Outras dicas
Experimente isso:
((.|\n)*)<FooBar>
Basicamente, diz "qualquer personagem ou uma nova linha" zero repetido ou mais vezes.
Se você estiver usando a pesquisa Eclipse, pode ativar a opção "Dotall" para fazer ''. Combine qualquer caractere, incluindo delimitadores de linha: basta adicionar "(? s)" no início da sua sequência de pesquisa. Exemplo:
(?s).*<FooBar>
A questão é, pode .
correspondência de padrão algum personagem? A resposta varia de motor para motor. A principal diferença é se o padrão é usado por uma biblioteca POSIX ou não-Posix Regex.
Nota especial sobre Lua-padrão: eles não são considerados expressões regulares, mas .
corresponde a qualquer char lá, o mesmo que os motores baseados em Posix.
Outra nota sobre Matlab e oitava: a .
corresponde a qualquer char por padrão (demonstração): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');
(tokens
conter a abcde\n fghij
item).
Além disso, em todo impulsoGRAMÁRIAS REGEX O DOT corresponde às quebras de linha por padrão. A gramática Ecmascript do Boost permite desativar isso com regex_constants::no_mod_m
(fonte).
Quanto a oráculo (é baseado em Posix), use n
opção (demonstração): select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
Motores baseados em Posix:
Uma mera .
Já corresponde às quebras de linha, sem necessidade de usar modificadores, veja Bash (demonstração).
o tcl (demonstração), PostGresql (demonstração), r (Tre, base R Base R motor padrão sem perl=TRUE
, para base r com perl=TRUE
ou para Stringr/stringi padrões, use o (?s)
modificador embutido) (demonstração) também tratar .
o mesmo caminho.
No entanto, a maioria das ferramentas baseadas em POSIX processam a linha de entrada por linha. Por isso, .
Não corresponde às quebras da linha apenas porque elas não estão no escopo. Aqui estão alguns exemplos de como substituir isso:
- sed - Existem várias soluções alternativas, o mais preciso, mas não muito seguro, é
sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'
(H;1h;$!d;x;
arrasta o arquivo na memória). Se linhas inteiras devem ser incluídas,sed '/start_pattern/,/end_pattern/d' file
(Remover do início terminará com linhas correspondentes incluídas) oused '/start_pattern/,/end_pattern/{{//!d;};}' file
(com linhas correspondentes excluídas) pode ser considerado. - perl -
perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"
(-0
arrasta o arquivo inteiro na memória,-p
imprime o arquivo após aplicar o script dado por-e
). Observe isso usando-000pe
Invocará o arquivo e ativará o 'modo de parágrafo', onde a Perl usa novas linhas consecutivas (\n\n
) como o separador de registros. - GNU-GREP -
grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file
. Aqui,z
Ativa o arrasto de arquivo,(?s)
Ativa o modo Dotall para o.
padronizar,(?i)
Ativa o modo insensível ao caso,\K
omite o texto correspondido até agora,*?
é um quantificador preguiçoso,(?=<Foobar>)
corresponde à localização antes<Foobar>
. - pcregrep -
pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file
(M
Ativa o arquivo de arquivo aqui). Observaçãopcregrep
é uma boa solução para Mac OSgrep
usuários.
Motores que não são baseados em Posix:
- php - Usar
s
modificador Modificador PCRE_DOTALL:preg_match('~(.*)<Foobar>~s', $s, $m)
(demonstração) - C# - Usar
RegexOptions.Singleline
bandeira (demonstração):
-var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
-var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
- PowerShell - Usar
(?s)
opção embutida:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
- perl - Usar
s
modificador (ou(?s)
versão embutida no início) (demonstração):/(.*)<FooBar>/s
- Pitão - Usar
re.DOTALL
(oure.S
) sinalizadores ou(?s)
modificador embutido (demonstração):m = re.search(r"(.*)<FooBar>", s, flags=re.S)
(e depoisif m:
,print(m.group(1))
) - Java - Usar
Pattern.DOTALL
modificador (ou embutido(?s)
bandeira) (demonstração):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
- Groovy - Usar
(?s)
Modificador de padrão (demonstração):regex = /(?s)(.*)<FooBar>/
- scala - Usar
(?s)
modificador (demonstração):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
- JavaScript - Usar
[^]
ou soluções alternativas[\d\D]
/[\w\W]
/[\s\S]
(demonstração):s.match(/([\s\S]*)<FooBar>/)[1]
- C ++ (
std::regex
) Usar[\s\S]
ou as soluções alternativas do JS (demonstração):regex rex(R"(([\s\S]*)<FooBar>)");
- vba - Use a mesma abordagem que em JavaScript,
([\s\S]*)<Foobar>
. - rubi - Usar
/m
Multilina modificador (demonstração):s[/(.*)<Foobar>/m, 1]
- vai - Use o modificador embutido
(?s)
no começo (demonstração):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
- rápido - Usar
dotMatchesLineSeparators
ou (mais fácil) passar o(?s)
Modificador embutido para o padrão:let rx = "(?s)(.*)<Foobar>"
- Objective-C - o mesmo que Swift,
(?s)
funciona mais fácil, mas aqui está como o a opção pode ser usada:NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:®exError];
- re2, Google-Apps-Script - Usar
(?s)
modificador (demonstração):"(?s)(.*)<Foobar>"
(nas planilhas do Google,=REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")
)
Notas sobre (?s)
:
Na maioria dos motores não-posix, (?s)
Modificador embutido (ou opção de sinalização incorporada) pode ser usada para aplicar .
Para combinar quebras de linha.
Se colocado no início do padrão, (?s)
muda o bahavior de todos .
no padrão. Se o (?s)
é colocado em algum lugar após o começo, apenas aqueles .
serão afetados que estão localizados à direita a não ser que Este é um padrão passado para Python re
. Em Python re
, independentemente do (?s)
Localização, todo o padrão .
são afetados. o (?s)
O efeito é parado de usar (?-s)
. Um grupo modificado pode ser usado para afetar apenas uma faixa especificada de um padrão regex (por exemplo Delim1(?s:.*?)\nDelim2.*
fará o primeiro .*?
combina com as novas linhas e a segunda .*
só corresponderá ao restante da linha).
Nota posix:
Em motores não régicos, para combinar com qualquer char, [\s\S]
/ [\d\D]
/ [\w\W]
construções podem ser usadas.
Em Posix, [\s\S]
não está correspondendo a nenhum char (como em JavaScript ou em qualquer motor não-posix) porque as sequências de escape regex não são suportadas dentro de expressões de suporte. [\s\S]
é analisado como expressões de suporte que correspondem a um único char, \
ou s
ou S
.
Em JavaScript, use /[\S\s]*<Foobar>/
. Fonte
([\s\S]*)<FooBar>
The dot matches all except newlines (\r\n). So use \s\S, which will match ALL characters.
In Ruby ruby you can use the 'm
' option (multiline):
/YOUR_REGEXP/m
See the Regexp documentation on ruby-doc.org for more information.
we can also use
(.*?\n)*?
to match everything including newline without greedy
This will make the new line optional
(.*?|\n)*?
"."
normally doesn't match line-breaks. Most regex engines allows you to add the S
-flag (also called DOTALL
and SINGLELINE
) to make "."
also match newlines.
If that fails, you could do something like [\S\s]
.
For Eclipse worked following expression:
Foo
jadajada Bar"
Regular-Expression:
Foo[\S\s]{1,10}.*Bar*
/(.*)<FooBar>/s
the s causes Dot (.) to match carriage returns
In java based regular expression you can use [\s\S]
Note that (.|\n)*
can be less efficient than (for example) [\s\S]*
(if your language's regexes support such escapes) and than finding how to specify the modifier that makes . also match newlines. Or you can go with POSIXy alternatives like [[:space:][:^space:]]*
.
Use RegexOptions.Singleline, it changes the meaning of . to include newlines
Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);
Solution:
Use pattern modifier sU will get the desired matching in PHP.
example:
preg_match('/(.*)/sU',$content,$match);
Source:
http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php
In the context of use within languages, regular expressions act on strings, not lines. So you should be able to use the regex normally, assuming that the input string has multiple lines.
In this case, the given regex will match the entire string, since "<FooBar>" is present. Depending on the specifics of the regex implementation, the $1 value (obtained from the "(.*)") will either be "fghij" or "abcde\nfghij". As others have said, some implementations allow you to control whether the "." will match the newline, giving you the choice.
Line-based regular expression use is usually for command line things like egrep.
I had the same problem and solved it in probably not the best way but it works. I replaced all line breaks before I did my real match:
mystring= Regex.Replace(mystring, "\r\n", "")
I am manipulating HTML so line breaks don't really matter to me in this case.
I tried all of the suggestions above with no luck, I am using .Net 3.5 FYI
In Javascript you can use [^]* to search for zero to infinite characters, including line breaks.
$("#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>
generally . doesn't match newlines, so try ((.|\n)*)<foobar>
I wanted to match a particular if block in java
...
...
if(isTrue){
doAction();
}
...
...
}
If I use the regExp
if \(isTrue(.|\n)*}
it included the closing brace for the method block so I used
if \(!isTrue([^}.]|\n)*}
to exclude the closing brace from the wildcard match.
Often we have to modify a substring with a few keywords spread across lines preceding the substring. Consider an xml element:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
Suppose we want to modify the 81, to some other value, say 40. First identify .UID.21..UID.
, then skip all characters including \n
till .PercentCompleted.
. The regular expression pattern and the replace specification are:
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>
The subgroup (.|\n)
is probably the missing group $3
. If we make it non-capturing by (?:.|\n)
then the $3
is (<PercentComplete>)
. So the pattern and replaceSpec
can also be:
pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")
and the replacement works correctly as before.