Salvataggio delle sottostringhe utilizzando le espressioni regolari
-
26-09-2019 - |
Domanda
Sono nuovo di espressioni regolari in Java (o qualsiasi altro linguaggio, è per questo) e sto volendo fare un ritrovamento che li utilizzano. La parte difficile che non capisco come fare è sostituire qualcosa dentro la stringa che le partite.
Ad esempio, se la linea che sto cercando è
Person item6 [can {item thing [wrap]}]
Sono in grado di scrivere una regex che trova quella linea, ma trovare ciò che la parola "cosa" è (come si può differire tra linee differenti) è il mio problema. Mi può essere utile per sostituire o quella parola con qualcos'altro o salvarlo in una variabile per più tardi. C'è un modo semplice per farlo usando il motore regex Java?
Soluzione
Sì. Si avvolgono in "gruppi di cattura", che è solo un po 'di () intorno alla parte dell'espressione regolare che corrisponde alla parola interessante.
Ecco un esempio:
public static void main(String[] args) {
Pattern pat = Pattern.compile("testing (\\d+) widgets");
String text = "testing 5 widgets";
Matcher matcher = pat.matcher(text);
if (matcher.matches()) {
System.out.println("Widgets tested : " + matcher.group(1));
} else {
System.out.println("No match");
}
}
Pattern e Matcher provengono da java.util.regex. Ci sono alcune scorciatoie nella classe String, ma questi sono i più flessibili
Altri suggerimenti
La specifica problema non è molto chiaro, ma qui ci sono alcune idee che potrebbero funzionare:
Usa lookarounds e replaceAll/First
La seguente espressione regolare corrisponde al \w+
che è preceduta dalla "{item "
corda e seguito dalla " ["
stringa. Lookarounds sono utilizzati per corrispondere esattamente solo la \w+
. Metacaratteri {
e [
sono scappati, se necessario.
String text =
"Person item6 [can {item thing [wrap]}]\n" +
"Cat item7 [meow meow {item thang [purr]}]\n" +
"Dog item8 [maybe perhaps {itemmmm thong [woof]}]" ;
String LOOKAROUND_REGEX = "(?<=\\{item )\\w+(?= \\[)";
System.out.println(
text.replaceAll(LOOKAROUND_REGEX, "STUFF")
);
Questo stampa:
Person item6 [can {item STUFF [wrap]}]
Cat item7 [meow meow {item STUFF [purr]}]
Dog item8 [maybe perhaps {itemmmm thong [woof]}]
Bibliografia
Usa gruppi di cattura, invece di lookarounds
Lookarounds dovrebbe essere usato con giudizio. Lookbehinds in particolare in Java è molto limitata. Una tecnica più comunemente applicato è quello di utilizzare gruppi di cattura per abbinare più che solo le parti interessanti.
La seguente espressione regolare corrisponde a un modello simile da prima, \w+
, ma comprende anche la "{item "
prefisso e " ["
suffisso. Inoltre, il m
in item
può ripetere senza limitazioni (cosa che non può essere eguagliata in un lookbehind in Java).
String CAPTURING_REGEX = "(\\{item+ )(\\w+)( \\[)";
System.out.println(
text.replaceAll(CAPTURING_REGEX, "$1STUFF$3")
);
Questo stampa:
Person item6 [can {item STUFF [wrap]}]
Cat item7 [meow meow {item STUFF [purr]}]
Dog item8 [maybe perhaps {itemmmm STUFF [woof]}]
Il nostro modello ha 3 gruppi di cattura:
(\{item+ )(\w+)( \[)
\________/\___/\___/
group 1 2 3
Si noti che non possiamo semplicemente sostituire quello che abbiamo fatto coincidere con "STUFF"
, perché abbiniamo alcune parti "estranee". Non siamo interessati a loro sostituzione, così abbiamo catturare queste parti e basta metterli di nuovo nella stringa di sostituzione. Il modo in cui si fa riferimento a ciò che un gruppo catturato in stringhe di sostituzione in Java è quello di utilizzare il sigillo $
; così il $1
e $3
nell'esempio precedente.
Bibliografia
Usa un Matcher
per una maggiore flessibilità
Non tutto può essere fatto con stringhe di sostituzione. Java non ha post-elaborazione per capitalizzare una stringa catturato, per esempio. In questi scenari di sostituzione più generali, è possibile utilizzare un ciclo Matcher
come il seguente:
Matcher m = Pattern.compile(CAPTURING_REGEX).matcher(text);
StringBuffer sb = new StringBuffer();
while (m.find()) {
System.out.println("Match found");
for (int i = 0; i <= m.groupCount(); i++) {
System.out.printf("Group %d captured <%s>%n", i, m.group(i));
}
m.appendReplacement(sb,
String.format("%s%s %<s and more %<SS%s",
m.group(1), m.group(2), m.group(3)
)
);
}
m.appendTail(sb);
System.out.println(sb.toString());
Il dispositivo stampa di cui sopra:
Match found
Group 0 captured <{item thing [>
Group 1 captured <{item >
Group 2 captured <thing>
Group 3 captured < [>
Match found
Group 0 captured <{item thang [>
Group 1 captured <{item >
Group 2 captured <thang>
Group 3 captured < [>
Match found
Group 0 captured <{itemmmm thong [>
Group 1 captured <{itemmmm >
Group 2 captured <thong>
Group 3 captured < [>
Person item6 [can {item thing thing and more THINGS [wrap]}]
Cat item7 [meow meow {item thang thang and more THANGS [purr]}]
Dog item8 [maybe perhaps {itemmmm thong thong and more THONGS [woof]}]
Bibliografia
-
java.util.regex.Pattern
-
java.util.regex.Matcher
-
group(int)
- stringhe accesso individuale catturati -
appendReplacement
- purtroppo,StringBuffer
-only
-
-
java.util.Formatter
- utilizzato inprintf
eString.format
nell'esempio sopra