Par exemple, cette expression régulière
(.*)<FooBar>
correspondra:
abcde<FooBar>
Mais comment puis-je le faire correspondre sur plusieurs lignes?
abcde
fghij<FooBar>
Par exemple, cette expression régulière
(.*)<FooBar>
correspondra:
abcde<FooBar>
Mais comment puis-je le faire correspondre sur plusieurs lignes?
abcde
fghij<FooBar>
Réponses:
Cela dépend de la langue, mais il devrait y avoir un modificateur que vous pouvez ajouter au modèle d'expression régulière. En PHP c'est:
/(.*)<FooBar>/s
Le s à la fin fait correspondre le point à tous les caractères, y compris les retours à la ligne.
s
modificateur. Au lieu de cela, faites [^]*
pour le même effet.
m
modificateur
Essaye ça:
((.|\n)*)<FooBar>
Il dit essentiellement "n'importe quel caractère ou une nouvelle ligne" répété zéro ou plusieurs fois.
((.|\n|\r)*)<FooBar>
[\s\S]*
ou (?s).*
.
La question est: le .
motif peut-il correspondre à n'importe quel caractère? La réponse varie d'un moteur à l'autre. La principale différence est de savoir si le modèle est utilisé par une bibliothèque d'expression régulière POSIX ou non POSIX.
Note spéciale sur lua-patterns: elles ne sont pas considérées comme des expressions régulières, mais .
correspondent à n'importe quel caractère, comme les moteurs basés sur POSIX.
Une autre note sur matlab et octave: le .
correspond à n'importe quel caractère par défaut ( démo ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');
( tokens
contient un abcde\n fghij
élément).
Aussi, dans tous renforcerles grammaires regex du point correspondent aux sauts de ligne par défaut. La grammaire ECMAScript de Boost vous permet de désactiver cette option avec regex_constants::no_mod_m
( source ).
Pour ce qui est de oracle(il est basé sur POSIX), utilisez l' n
option ( démo ):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
Moteurs basés sur POSIX :
Un simple .
correspond déjà à des sauts de ligne, pas besoin d'utiliser de modificateurs, voirfrapper( démo ).
le tcl( démo ),postgresql( démo ),r(TRE, moteur par défaut de la base R avec non perl=TRUE
, pour la base R avec perl=TRUE
ou pour les modèles stringr / stringi , utilisez le (?s)
modificateur inline) ( démo ) traiter également de .
la même manière.
Cependant , la plupart des outils basés sur POSIX traitent les entrées ligne par ligne. Par conséquent, .
ne correspond pas aux sauts de ligne simplement parce qu'ils ne sont pas dans la portée. Voici quelques exemples pour contourner cela:
sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'
( H;1h;$!d;x;
glisse le fichier dans la mémoire). Si des lignes entières doivent être incluses, sed '/start_pattern/,/end_pattern/d' file
(la suppression du début se terminera avec les lignes correspondantes incluses) ou sed '/start_pattern/,/end_pattern/{{//!d;};}' file
(avec les lignes correspondantes exclues) peut être envisagée.perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"
( -0
met le fichier entier en mémoire, -p
imprime le fichier après avoir appliqué le script donné par -e
). Notez que l'utilisation -000pe
ralentira le fichier et activera le «mode paragraphe» où Perl utilise des sauts de ligne consécutifs ( \n\n
) comme séparateur d'enregistrement.grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file
. Ici, z
active le slurping de fichier, (?s)
active le mode DOTALL pour le .
motif, (?i)
active le mode insensible à la casse, \K
omet le texte correspondant jusqu'à présent, *?
est un quantificateur paresseux, (?=<Foobar>)
correspond à l'emplacement précédent <Foobar>
.pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file
( M
active le fichier slurping ici). Remarque pcregrep
est une bonne solution pour les grep
utilisateurs de Mac OS .Moteurs non basés sur POSIX :
s
modificateur PCRE_DOTALL : preg_match('~(.*)<Foobar>~s', $s, $m)
( démo )RegexOptions.Singleline
drapeau ( démo ): var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
(?s)
option en ligne:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
s
modificateur (ou une (?s)
version en ligne au début) ( démo ):/(.*)<FooBar>/s
re.DOTALL
(ou re.S
) des drapeaux ou un (?s)
modificateur en ligne ( démo ): m = re.search(r"(.*)<FooBar>", s, flags=re.S)
(puis if m:
, print(m.group(1))
)Pattern.DOTALL
modificateur (ou le (?s)
drapeau en ligne ) ( démo ):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
(?s)
modificateur in-pattern ( démo ):regex = /(?s)(.*)<FooBar>/
(?s)
modificateur ( démo ):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
[^]
ou solutions [\d\D]
/ [\w\W]
/ [\s\S]
( démo ):s.match(/([\s\S]*)<FooBar>/)[1]
std::regex
) Utilisation [\s\S]
ou solutions de contournement JS ( démo ):regex rex(R"(([\s\S]*)<FooBar>)");
vba vbscript- Utilisez la même approche que JavaScript, ([\s\S]*)<Foobar>
. ( REMARQUE : la MultiLine
propriété de l'
RegExp
objet est parfois considérée à tort comme l'option d'autoriser la .
correspondance entre les sauts de ligne, alors qu'en fait, elle modifie uniquement le comportement ^
et $
pour correspondre au début / fin des lignes plutôt qu'aux chaînes , comme dans l'expression régulière JS ) comportement.)
rubis- Utilisez le modificateur /m
MULTILINE ( démo ):s[/(.*)<Foobar>/m, 1]
(?s)
: regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]
( démo )stringr
/ stringi
regex qui sont alimentées par le moteur ICU regex, utilisent également (?s)
: stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]
( démo )(?s)
au début ( démo ):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
dotMatchesLineSeparators
ou (plus facile) passez le (?s)
modificateur en ligne au motif:let rx = "(?s)(.*)<Foobar>"
(?s)
fonctionne le plus facilement, mais voici comment l' option peut être utilisée :NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators error:®exError];
(?s)
modificateur ( démo ): "(?s)(.*)<Foobar>"
(dans Google Spreadsheets, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")
)NOTES SUR(?s)
:
Dans la plupart des moteurs non POSIX, (?s)
le modificateur en ligne (ou l'option d'indicateur intégré) peut être utilisé pour appliquer .
pour correspondre aux sauts de ligne.
S'il est placé au début du motif, (?s)
change le comportement de tous .
dans le motif. Si le (?s)
est placé quelque part après le début, seuls ceux .
qui sont situés à droite de celui-ci seront affectés, sauf s'il s'agit d'un modèle transmis à Python re
. En Python re
, quel que soit l' (?s)
emplacement, l'ensemble du modèle .
est affecté. L' (?s)
effet n'est plus utilisé (?-s)
. Un groupe modifié peut être utilisé pour n'affecter qu'une plage spécifiée d'un modèle d'expression régulière (par exemple Delim1(?s:.*?)\nDelim2.*
, fera la première .*?
correspondance entre les nouvelles lignes et la seconde .*
ne correspondra qu'au reste de la ligne).
Remarque POSIX :
Dans les moteurs d'expression régulière non POSIX, pour correspondre à n'importe quel caractère, les constructions [\s\S]
/ [\d\D]
/ [\w\W]
peuvent être utilisées.
Dans POSIX, [\s\S]
ne correspond à aucun caractère (comme dans JavaScript ou tout moteur non-POSIX) car les séquences d'échappement regex ne sont pas prises en charge dans les expressions entre crochets. [\s\S]
est analysé comme des expressions entre crochets qui correspondent à un seul caractère, \
ou s
ou S
.
#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m
pour leurs drapeaux d'expression régulière afin de refléter cela. Et l'arbitre est toujours les modificateurs en ligne. Où (?-sm)(?s).*
réinitialise.
.
correspond à n'importe quel caractère (y compris les sauts de ligne). Voir cette démo Bash en ligne .
Go
dans la réponse!
Si vous utilisez la recherche Eclipse, vous pouvez activer l'option "DOTALL" pour faire '.' faire correspondre n'importe quel caractère, y compris les délimiteurs de ligne: ajoutez simplement "(? s)" au début de votre chaîne de recherche. Exemple:
(?s).*<FooBar>
(?s)
=>(?m)
Dans de nombreux dialectes regex, /[\S\s]*<Foobar>/
fera exactement ce que vous voulez. La source
([\s\S]*)<FooBar>
Le point correspond à tous sauf les sauts de ligne (\ r \ n). Utilisez donc \ s \ S, qui correspondra à TOUS les caractères.
[text rangeOfString:regEx options:NSRegularExpressionSearch]
. Merci!
<FooBar>
En rubis rubisvous pouvez utiliser l' m
option ' ' (multiligne):
/YOUR_REGEXP/m
Voir la documentation Regexp sur ruby-doc.org pour plus d'informations.
on peut aussi utiliser
(.*?\n)*?
pour correspondre à tout, y compris la nouvelle ligne sans gourmandise
Cela rendra la nouvelle ligne facultative
(.*?|\n)*?
"."
ne correspond normalement pas aux sauts de ligne. La plupart des moteurs d'expression régulière vous permettent d'ajouter le S
-flag (également appelé DOTALL
et SINGLELINE
) pour faire "."
correspondre également les nouvelles lignes. Si cela échoue, vous pourriez faire quelque chose comme [\S\s]
.
/(.*)<FooBar>/s
le s fait que Dot (.) correspond aux retours chariot
s
drapeaux existent dans PCRE, le moteur le plus complet (disponible en Perl et PHP). PCRE a 10 drapeaux (et beaucoup d'autres fonctionnalités) tandis que JavaScript n'a que 3 drapeaux ( gmi
).
Dans l'expression régulière basée sur java, vous pouvez utiliser [\s\S]
s
drapeau au modèle en Java et JavaScript n'a pas le s
drapeau.
Notez que cela (.|\n)*
peut être moins efficace que (par exemple) [\s\S]*
(si les expressions rationnelles de votre langue prennent en charge ces échappements) et que de trouver comment spécifier le modificateur qui le fait. correspondent également aux nouvelles lignes. Ou vous pouvez aller avec des alternatives POSIXy comme [[:space:][:^space:]]*
.
Utiliser le modificateur de motif sU obtiendra la correspondance souhaitée en PHP.
preg_match('/(.*)/sU',$content,$match);
http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php
Dans le contexte d'une utilisation dans les langues, les expressions régulières agissent sur les chaînes, pas sur les lignes. Vous devriez donc pouvoir utiliser l'expression régulière normalement, en supposant que la chaîne d'entrée comporte plusieurs lignes.
Dans ce cas, l'expression régulière donnée correspondra à la chaîne entière, car "<FooBar>" est présent. Selon les spécificités de l'implémentation de l'expression régulière, la valeur $ 1 (obtenue à partir du "(. *)") Sera soit "fghij" soit "abcde \ nfghij". Comme d'autres l'ont dit, certaines implémentations vous permettent de contrôler si le "." correspondra à la nouvelle ligne, vous donnant le choix.
L'expression régulière basée sur la ligne est généralement utilisée pour les choses en ligne de commande comme egrep.
J'ai eu le même problème et je l'ai résolu probablement pas de la meilleure façon, mais cela fonctionne. J'ai remplacé tous les sauts de ligne avant de faire mon vrai match:
mystring= Regex.Replace(mystring, "\r\n", "")
Je manipule du HTML, donc les sauts de ligne n'ont pas vraiment d'importance pour moi dans ce cas.
J'ai essayé toutes les suggestions ci-dessus sans succès, j'utilise .Net 3.5 FYI
(\s|\S)
semble faire l'affaire pour moi!
(?s)
pour faire .
correspondre tous les caractères. N'utilisez pas (\s|\S)
cela qui ralentira les performances.
En Javascript, vous pouvez utiliser [^] * pour rechercher des caractères de zéro à infini, y compris les sauts de ligne.
$("#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>
généralement . ne correspond pas aux nouvelles lignes, alors essayez((.|\n)*)<foobar>
\r
.:((?:.|\r?\n)*)<foobar>
Je voulais faire correspondre un bloc if particulier en java
...
...
if(isTrue){
doAction();
}
...
...
}
Si j'utilise regExp
if \(isTrue(.|\n)*}
il comprenait l'accolade de fermeture pour le bloc de méthode, donc j'ai utilisé
if \(!isTrue([^}.]|\n)*}
pour exclure l'accolade de fermeture de la correspondance générique.
Souvent, nous devons modifier une sous-chaîne avec quelques mots clés répartis sur les lignes précédant la sous-chaîne. Considérons un élément xml:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
Supposons que nous voulons modifier le 81, à une autre valeur, disons 40. Identifiez d'abord .UID.21..UID.
, puis ignorez tous les caractères, y compris \n
till .PercentCompleted.
. Le modèle d'expression régulière et la spécification de remplacement sont les suivants:
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>
Le sous (.|\n)
- groupe est probablement le groupe manquant $3
. Si nous le rendons non capturable d'ici (?:.|\n)
là, le $3
est (<PercentComplete>)
. Ainsi, le motif et replaceSpec
peut également être:
pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")
et le remplacement fonctionne correctement comme avant.
En général, la recherche de trois lignes consécutives dans Powershell ressemblerait à ceci:
$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
Bizarrement, ce serait du texte Unix à l'invite, mais du texte Windows dans un fichier:
$pattern = 'lineone
linetwo
linethree
'
Voici un moyen d'imprimer les fins de ligne:
'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'
# output
lineone\nlinetwo\nlinethree\n
Une façon serait d'utiliser le s
drapeau (tout comme la réponse acceptée):
/(.*)<FooBar>/s
Une deuxième façon serait d'utiliser l' m
indicateur (multiligne) et l'un des modèles suivants:
/([\s\S]*)<FooBar>/m
ou
/([\d\D]*)<FooBar>/m
ou
/([\w\W]*)<FooBar>/m
jex.im visualise les expressions régulières: