# Pattern.compile Syntax



## Hintertür (3. Aug 2011)

Morgen Commy,

ich hab mal folgenden Code gebastelt, weil ich aus nem Text (input, cmd rückgabe) einen bestimmten Teil haben möchte, undzwar ob auf einem Interface DHCP aktiv ist oder nicht. 

Kurz: Ich möchte einen Textausschnitt haben


```
public String textAuslesen(String input, String startOfInput, String endOfInput){
		Pattern p = Pattern.compile(".*?"+startOfInput+"\\s(.!?*?)\\s"+endOfInput);
		Matcher m = p.matcher(input);
		boolean matches = m.matches();
		int groupCount = m.groupCount();
		return m.group(1);
	}
```

Funktioniert im moment super! Doch sobald die Parameter folgendermaßen aussehen:


```
textAuslesen("Hallo wie geht es dir? Mir geht es sehr gut!", "dir", "gut");
```
schmeißt er ne Exception: No match found.

Wie bekomme ich jetzt in das Regex 
	
	
	
	





```
Pattern.compile(".*?"....
```
jetzt nocht >!< und >?< hinein, bzw generell Sonderzeichen?

Danke im vorraus!


----------



## Ariol (4. Aug 2011)

```
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTest
{

	public static String textAuslesen(String input, String startOfInput, String endOfInput)
	{
		Pattern p = Pattern.compile(".*" + startOfInput + "(.*)" + endOfInput + ".*");
		Matcher m = p.matcher(input);
		boolean matches = m.matches();
		int groupCount = m.groupCount();
		
		if(matches && groupCount > 0)
			return m.group(1);
		return "";
	}

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		System.out.println(textAuslesen("Hallo wie geht es dir? Mir geht es sehr gut!", "dir", "gut"));
	}

}
```


----------



## RySa (4. Aug 2011)

Also ich würd so etwas vorschlagen:

```
public static void main(String args[]){
		String input = "Hallo wie geht es dir? Mir geht es sehr gut!";
                String startOfInput = "dir";
                String endOfInput = "gut";
	        Pattern p = Pattern.compile(".*?"+startOfInput+"(.*?)"+endOfInput);
	        Matcher m = p.matcher(input);

	        while(m.find()){
	        	System.out.println(m.group(1));
	        }

	}
```

Ein Punkt heißt ja schon beliebiges Zeichen, da musst du nicht die Sonderzeichen extra angeben, die sind schon da mit drin


----------



## Hintertür (4. Aug 2011)

@ Ariol: top! danke deine weise hat funktioniert!! aber wie mache ich das dann mit den whitespaces?

ich will folgenden textausschnitt haben:




sprich: ich will gucken ob DHCP aktiv ist (auf dem bestimmten interface)... wie realisiere ich sowas? da es ja mit tabs und halt den whitespaces ist (inner cmd)

@RySa: danke für die antwort!  es lag an den \\s wie ich es herausgefunden hab^^


----------



## RySa (4. Aug 2011)

Ein Punkt nimmt auch Whitespaces an. d.h wenn du dir das (.*?) ausgeben lässt, und da drinne so etwas enthalten ist 

```
String s = "                ja              "
```
 , dann brauchst du es ja nur zu trimmen . Also 

```
String s = "                   Ja                  ";
s = s.trim();
```

Dann hast du im s nur noch "Ja";


----------



## Hintertür (4. Aug 2011)

es will einfach nicht klappen... hmmm 

sprich bei m.matches bricht er leider ab...

hmm ist das so schwer zu realisieren?^^

ich glaube man konnte sich die \r\n ect anzeigen lassen sprich wie in einer zeile... 
wisst ihr wie das geht? dann wäre das auch einfacher^^

€dit: so sieht mein code bis jetzt aus:
erstmal der cmd command:


```
public String netshellReadDHCP() throws IOException, InterruptedException { 
		Runtime rt = Runtime.getRuntime();
		Process p = null;
		p = rt.exec ("netsh interface ipv4 show addresses");
		InputStream in = p.getInputStream();
		String ausgabe = StringTools.stringFromInputStream(in);
//		System.out.print(ausgabe);
		
		String endausgabe = pm.textAuslesen2(ausgabe, "Konfiguration der Schnittstelle \"Drahtlosnetzwerkverbindung\"", "IP-Adresse", true);
		
		System.out.println(endausgabe);
		//er soll wenns es klappt die endausgabe zurückgeben, und nicht "" ;D
		return "";
                
	}
```

ich habe bei der pattern methode noch was geändert:


```
/**
	 * Diese Methode gibt einen gesuchten Textabschnitt wieder zurück. 
	 * startOfInput und endOfInput sind Case-Sensitiv!
	 * 
     * @autor Christopher Kröncke
	 * @param input Input Text
	 * @param startOfInput Anfang des gesuchten Zwischenabschnittes
	 * @param endOfInput Ende des gesuchten Zwischenabschnittes
	 * @param trimFirstWhitespace Trimmt die whitespaces der vorherigen parameter
	 * @return Gibt den Zwischenabschnitt zurück
	 */
	public String textAuslesen(String input, String startOfInput, String endOfInput, boolean trimInputWhitespace){
		if (trimInputWhitespace){
			input = input.trim();
		}
		Pattern p = Pattern.compile(".*?" + startOfInput + "(.*?)" + endOfInput + ".*?");
		Matcher m = p.matcher(input);
		boolean matches = m.matches();
		int groupCount = m.groupCount();
		if(matches && groupCount > 0){
            return m.group(1);
		}
        return "No Match";
	}
```

p.s: könnt ihr auch benutzen wenn ihr mögt^^


----------



## RySa (4. Aug 2011)

Wie wärs wenn du einfach mal nochmal nach "(?i)(?s).*?DHCP aktiviert:.*?(Ja|Nein).*?" suchst. Also so etwas:

```
public static void main(String[] args) {
	String input = "Konfiguration der Schnittstelle \"Drahtlosnetzwerkverbindung\" \n DHCP aktiviert:                  Ja                 \n IP Adresse:                      192.168.178.1        ";
        Pattern p = Pattern.compile("(?i)(?s).*?DHCP aktiviert:.*?(Ja|Nein).*?");
        Matcher m = p.matcher(input);
        while(m.find()){
        	System.out.println(m.group(1));
        }

	}
```

Ausserdem, (wenn ich mich nicht irre) musst du dem Matcher erstmal sagen "so, jetzt finde mal das nächste, das zutrifft" , also mit Matcher.find() - dann kannst du erst damit arbeiten. Mit  .matches() überprüfst du nur ob der mal mindestens 1 Treffer hat, der Matcher ist aber noch nicht an die Stelle der Treffer gegangen, musst du ihm erst mit .find() sagen.

Gruß


----------



## HoaX (4. Aug 2011)

Ohne komplizierte Regex gehts auch so:
Mittels String#split in die einzelnen Zeilen zerlegen und mit String#trim() die Leerzeichen außen herum entfernen.
Dann die Zeilen durchgehen und mit String#startWith die Zeile finden und mit String#endsWith auswerten.

Ist auch nicht viel mehr Code und auch für jemanden ohne Ahnung von Regex verständlich.


----------



## RySa (4. Aug 2011)

@ HoaX

Das mag ja sein, allerdings kann sich ein Wert, über mehrere Zeilen strecken und dann würde es nicht mehr so klappen. Und ich finde diese Regex ist gar nicht kompliziert, eher ganz anschaulich. Und falls jemand, wie du sagtest, keine Ahnung von Regex hat, dann wäre es jetzt der richtige Zeitpunkt sich mit denen auseinander zu setzen, weil die echt immer wieder zu gebrauchen sind.

Außerdem, nehme ich an, dass der TO eigentlich immer die Werte hinter name: haben möchte, also z.B IP Adresse:  192......., dann kann er einfach mal aus meinem letzten Beispiel ne Methode machen, der der Name übergeben wird, und dann einfach mal so gesucht wird: "(?i)(?s).*?"+name+":.*?(Ja|Nein).*?" , somit braucht er nur den kompletten String zu übergeben und den Namen. Das ist aber alles eine Sache der Implementierung.


----------



## Ariol (4. Aug 2011)

```
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTest
{

	public static boolean isDHCPEnabled(String input)
	{
		Pattern p = Pattern.compile("(?i)(?s).*DHCP aktiviert\\:\\s*(Ja|Nein).*");
		Matcher m = p.matcher(input);

		boolean matches = m.matches();
		if(!matches)
			return false;
		
		int groupCount = m.groupCount();
		String dhcpState = "Nein";
		if(groupCount > 0)
			dhcpState = m.group(1);
		return dhcpState.equals("Ja");
	}

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		System.out.println(isDHCPEnabled("Text davor\n    DHCP aktiviert:                       Nein\nText danach\n"));
		System.out.println(isDHCPEnabled("Text davor\n    DHCP aktiviert:                       Ja\nText danach\n"));
		System.out.println(isDHCPEnabled("Blub"));
	}

}
```

Works for me.

@RySa: Find brauchst du nicht, wenn du nur einmal prüfst:


			
				http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#matches(java.lang.String hat gesagt.:
			
		

> If a pattern is to be used multiple times, compiling it once and reusing it will be more efficient than invoking this method each time.


----------



## RySa (4. Aug 2011)

Hab ja gesagt "wenn ich mich nicht irre"  anscheinend hab ich mich geirrt  war aber so ne vermutung warum er bei ihm immer bei matches da "aufgegeben" hat  ich benutze allerding immer das find(), habe mir so angewöhnt und konnte mich bisher noch nicht beschweren  Also, die beiden Varianten funktionieren. Jetzt warten wa nur noch auf den TO ^^


----------



## Hintertür (5. Aug 2011)

so mädels,

habe beide varianten ausprobiert ;D  das problem: ich weiß bei Ariol nicht was in den input soll... weil der input ja folgendes ist:

Konfiguration der Schnittstelle "Drahtlosnetzwerkverbindung"
    DHCP aktiviert:                       Ja
    Schnittstellenmetrik:                      50

Konfiguration der Schnittstelle "LAN-Verbindung"
    DHCP aktiviert:                       Ja
    IP-Adresse:                           192.168.160.112
    Subnetzpräfix:                        192.168.160.0/24 (Maske 255.255.255.0)

    Standardgateway:                      192.168.160.11
    Gatewaymetrik:                        0
    Schnittstellenmetrik:                      10

Konfiguration der Schnittstelle "Loopback Pseudo-Interface 1"
    DHCP aktiviert:                       Nein
    IP-Adresse:                           127.0.0.1
    Subnetzpräfix:                        127.0.0.0/8 (Maske 255.0.0.0)
    Schnittstellenmetrik:                      50

soll ich das ganze in den input dann reinpacken? sorry das ich mich so blöd anstelle :/

€dit: mist er nimmt die whitespaces hier im forum nicht an °-°   siehe bild oben


----------



## RySa (5. Aug 2011)

Wenn du es ganz genau haben willst:

```
public static void main(String[] args) {
    String input = "Konfiguration der Schnittstelle \"Drahtlosnetzwerkverbindung\" \n DHCP aktiviert:                  Ja                 \n IP Adresse:                      192.168.178.1        "; //usw, halt der ganze input von dir
    String start = "\"Drahtlosnetzwerkverbindung\"";
    String end = "IP Adresse";
        Pattern p = Pattern.compile("(?i)(?s)"+start+".*?DHCP aktiviert:.*?(Ja|Nein).*?"+end);
        Matcher m = p.matcher(input);
        while(m.find()){
            System.out.println(m.group(1));
        }
 
    }
```


----------



## Hintertür (5. Aug 2011)

ich danke Ariol und dir RySe auch besonders!! funktioniert jetzt  
folgendes ist jetzt mein programmcode:


```
public String dhcp(String input, String interfaceName) throws IOException, InterruptedException{
            Pattern pattern = Pattern.compile("(?i)(?s)\""+interfaceName+"\".*?DHCP aktiviert:.*?(Ja|Nein).*?IP-Adresse");
            Matcher m = pattern.matcher(input);
            boolean matches =m.find();
            int groupCount = m.groupCount();
            if(matches && groupCount > 0){
                  if(m.group(1).equals("Ja")){
                        return "DHCP-On";
                  }else{
                        return "DHCP-Off";
                  }
            }
        return "No Match";
      }
```

und die methode funktioniert super auf DHCP  danke nochmal leute!


----------



## RySa (5. Aug 2011)

Immer wieder gern  (ich mag's mit Regex "zu experimentieren")


----------



## eRaaaa (5. Aug 2011)

Eieiei, die armen nicht-Windows-User und die, die nicht deutsch eingestellt haben... 
Man könnte auch ganz ohne kompliziertem Regex auskommen und den Scanner nutzen 

```
Scanner sc = new Scanner(input);
		while (sc.findWithinHorizon("DHCP aktiviert:", 0) != null) {
			System.out.println(sc.nextLine().trim());
		}
```
oder evtl. um doch noch ein wenig sprachunabhängiger zu sein (ka ob da bei englisch so etwas wie DHCP activated steht :bahnhof:= ) eben doch ein wenig Regex - so etwas wie:

```
sc.findWithinHorizon("DHCP .+?:", 0) != null) {
```


----------

