Est-il possible de faire une correspondance de modèle multiline à l'aide de sed
, awk
ou grep
? Prenons par exemple, je voudrais obtenir toutes les lignes entre {
et }
Donc, il devrait être capable de faire correspondre
1. {}
2. {.....}
3. {.....
.....}
Initialement la question utilisée <p>
par exemple. Édité la question à utiliser {
et}
.
Bien que je suis d'accord avec le conseil ci-dessus, que vous voudrez obtenir un analyseur pour quelque chose de plus que de minuscule ou totalement ad-hoc, c'est (à peine ;-) possible de faire correspondre des blocs multilignes entre les accessoires bouclés avec SED.
Voici une version de débogage du code SED
sed -n '/[{]/,/[}]/{
p
/[}]/a\
end of block matching brace
}' *.txt
Quelques notes,
/[{]/,/[}]/
est une expression de plage. Cela signifie numériser jusqu'à ce que vous trouviez quelque chose qui correspond au premier modèle (/[{]/)
Puis numériser jusqu'à ce que vous trouviez le 2e motif (/[}]/)
Ensuite, effectuez toutes les actions que vous trouvez entre le {} dans le code SED. Dans ce cas, "P" et le code de débogage. (Non expliqué ici, utilisez-le, modez-le ou sortez-le comme fonctionne le mieux pour vous).Vous pouvez supprimer le/[}]/a\fin du débogage du bloc lorsque vous prouvez à votre satisfaction que le code correspond vraiment à des blocs de correspondance délimités par {,}.
Cet échantillon de code sautera tout ce qui n'est pas à l'intérieur d'une paire d'attelle bouclée. Comme indiqué par d'autres personnes ci-dessus, être inconforté si vous avez un supplément {,} intégré dans des chaînes, des REG-EXPS, etc., ou où la brace de fermeture est la même ligne, (avec merci à fred.bear)
J'espère que ça aide.
Vous pouvez utiliser l'option -M (multiline) pour PCREGREP:
pcregrep -M '\{(\s*.*\s*)*\}' test.txt
\ s est blancheur (y compris de nouvelles lignes), cela correspond donc à zéro ou à plus d'occurrences de (Espace WhitSpace suivi de. * suivi de WhitSpace), toutes enfermées dans des accolades.
Mettre à jour:
Cela devrait faire la correspondance non gourmande:
pcregrep -n -M '\{(\n*.*?\n*)*?\}' test.txt
parser.awk:
#!/usr/bin/awk -f
function die(msg) { print msg > "/dev/stderr"; exit 1 }
BEGIN {
FS=opener
if (mode=="l") linewise=1
else if (mode=="i") trim_closer=length(closer)
else if (mode!="a") die("mode must be one of: l,i,a")
}
{
live=level
for (f=1; f<=NF; f++) {
if (f>1) {
live=++level
if (mode=="i" && level>1 || mode=="a") printf "%s", opener
}
cur=$f
level-=gsub(closer, "", cur)
if (level<0) die("Unbalanced")
if (!linewise) {
cur=$f
if (sub(".*" closer, "", cur)) printf "%s",
substr($f, 1, length($f) - length(cur) - (level ? 0 : trim_closer))
else if (live) printf "%s", $f
}
}
if (live) {
if (linewise) print
else print ""
}
}
END { if (level>0) die("Unbalanced") }
Appeler comme awk -v'opener={' -v'closer=}' -v'mode=a' -f parser.awk
. Si le mode est a
, il imprime les supports et le contenu de tous les plus externes et équilibrés {...}
; Si le mode est i
, il imprime uniquement leur contenu; Si le mode est l
, il imprime des lignes complètes où la plus externe {...}
commence, reste ouvert ou ferme.
XML comme des expressions telles que (étiquettes à infinie récursives) n'est pas une "langue régulière" ne peut donc pas être analysée par des expressions régulières (regex). Voici pourquoi:
https://stackoverflow.com/questions/1732348/regex-match-Open-tags-except-xhtml-elf-contenait-tags/
http://www.perlmonks.org/?node_id=66835
https://stackoverflow.com/questions/1379524/textual-protocol-qui-is-not-a-regular-language
Les expressions régulières ne peuvent pas trouver des parenthèses imbriquées correspondant.
Si vous êtes certain qu'il n'y aura aucune paire de parenthèses imbriquée à l'intérieur de celle que vous recherchez, vous pouvez rechercher jusqu'à la première fermeture. Par exemple:
sed -r 's#\{([^}])\}#\1#'
Cela remplacera tout le texte de '{' à '}' avec ce qui entre entre eux.