# im String ersetzen, wenn...



## magic_halli (2. November 2007)

Hi,

ich habe einen String, der in etwa so aussehen kann:

```
String str = "sigma_v=sqrt(sigma^2+3*tau^2)";
```
Jetzt möchte ich in solch einem String bspw. 'sigma' ersetzen (z.B. durch einen Zahlenwert).
Es soll aber nur ersetzt werden, wenn links vom gefundenen Wort (wäre hier 'sigma') entweder ein Leerzeichen oder math. Zeichen ( +,-,*,/,(,),^ etc. ) *UND* rechts vom gefundenen Wort ebenfalls Leerzeichen, math.Zeichen, oder ein Stringende vorkommt
Hier in diesem Fall würde/sollte dann 'sigma' ersetzt werden, aber nicht das sigma von 'sigma_v'!
Wie ich ersetze weis ich. Mir geht es nur um das Überprüfen dieser Kriterien...

Wie kann ich das anstellen?

Danke und Gruß.


----------



## Andron (2. November 2007)

Hmm, ich würde zuerst das String mit StringTokenizer passend "zerstückeln".

z.B.
StringTokenizer tk = new StringTokenizer (str, "+ - * / ( ) ^");
Das Problem wäre dabei, dass du auch solche Schlüsselwörter wie "sqrt" abfangen musst.
In diesem Beispiel würdest du folgende Strings bekommen:
sigma_v=sqrt
sigma
2
3
tau

Nun weißt du, dass 1 String-Teil nicht ersetzt werden darf. Im nächsten Schritt prüfst du, ob es sich um eine Zahl handelt, wenn nicht, ob es ein Schlüsselwort ist, wenn nicht, ersetzen.


----------



## Tobias Köhler (2. November 2007)

Noch ein Tipp wäre wenn du dir die Methoden indexOf und substring anguckst


----------



## magic_halli (2. November 2007)

Ok, danke für den Tip mit dem StringTokenizer... ich werd mich mal ransetzen und probieren.


----------



## magic_halli (5. November 2007)

So, also ich komme irgendwie nicht weiter... ich kann mir zwar per StringTokenizer an den bestimmten Stellen den String zerlegen lassen, aber sobald ich eben per String.replaceAll() ersetzen will, ist es eigentlich völlig egal, wo und wie ich einen String aufsplitte - es wird eben einfach rücksichtslos ersetzt!
Bspw. wird eben auch in 'sigma_v' das sigma ersetzt, obwohl es ja für mich nichts mit 'sigma' zu tun hat, sondern ein eigenständiger Teilstring ist und somit auch unverändert bleiben soll!
Hat noch jemand ne Idee oder Vorschlag, wie ich mein Vorhaben erfolgreich umsetzen könnte?

Gruß.


----------



## Tobias Köhler (5. November 2007)

naja, replaceAll ist ja schon aussagekräftig, was das wohl macht
wie gesagt, du könntest dir ja auch mal indexOf angucken, sollte dir helfen


----------



## Ronin-Jay (5. November 2007)

Naja, Du darfst ja auch nicht einfach String.replaceAll() sagen, wenn Du nur ein bestimmtes Sigma ersetzen möchtest. Wenn Du den kompletten String mittels Tokenizer zerlegt hast, prüfst Du zunächst, ob ein komplettes Segment des Tokenizers nur mit 'sigma' gefüllt ist. Trifft dies zu, schaust Du Dir das Token davor und danach an und handelst nach Deinen Kriterien: 


> ...Es soll aber nur ersetzt werden, wenn links vom gefundenen Wort (wäre hier 'sigma') entweder ein Leerzeichen oder math. Zeichen ( +,-,*,/,(,),^ etc. ) UND rechts vom gefundenen Wort ebenfalls Leerzeichen, math.Zeichen, oder ein Stringende vorkommt



Wobei das Leerzeichen beim Tokenizer ja wegfällt.....


----------



## magic_halli (5. November 2007)

> Wenn Du den kompletten String mittels Tokenizer zerlegt hast, prüfst Du zunächst, ob ein komplettes Segment des Tokenizers nur mit 'sigma' gefüllt ist.


Wie prüfe ich das ab, ob es NUR mit sigma gefüllt ist?


----------



## magic_halli (5. November 2007)

Ist es vielleicht irgendwie möglich, ganz geziehlt auf einen Token zuzugreifen?
Ich kann mir ja mittels countTokens() die Anzahl der Tokens ermitteln. Jetzt würde ich gern auf bspw. Token Nummer 3 zugreifen, um diesen zu manipulieren.


----------



## MiMi (5. November 2007)

Du koenntest alle tokens in ein Array schreiben und dann gezielt auf eins zugreifen.


----------



## Andron (5. November 2007)

StringTokenizer tk = new StringTokenizer(str, "/ * usw.");
int counter = 0;
String myTk = null;
String editedString = null;
while(tk.hasMoreTokens())
{
      myTk = tk.nextToken();
      System.out.println(myTk);
      counter = ++;
      if(counter == 3) editedString  = editToken(myTk);
} 

private String editToken (String toEdit)
{
   String editedString = null;   
   // hier bearbeiten
   return editedString
}


----------



## Ronin-Jay (5. November 2007)

Wie mimij85 schon sagt, muß Du dann alle Token in eine ArrayLIst schreiben und kannst Du direkt über den Index auf ein Token zugreifen:


```
import java.util.ArrayList;
import java.util.StringTokenizer;

public class StrTokenizerExample {
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		String str 			   = "Ich bin mal ein längerer unsinniger Satz " +
							 	 "ohne jegliche Bedeutung.";
		StringTokenizer strTk  = new StringTokenizer(str);
		ArrayList       tkList = new ArrayList();
		while (strTk.hasMoreTokens()) {
			tkList.add(strTk.nextToken().toString());
		}
		System.out.println(tkList.get(2));
		
		
	}
}
```


----------



## MiMi (5. November 2007)

Andron hat gesagt.:


> StringTokenizer tk = new StringTokenizer(str, "/ * usw.");
> int counter = 0;
> String myTk = null;
> String editedString = null;
> ...




Andron, das ist ziemlich umstaendlich. Vorallem was soll 
counter = ++;
Also mit ner Arrayliste, ist das wesentlich einfacher, man muss nicht jedes mal alle tokens durchlaufen, und kann direkt auf das jeweilige zugreifen 

Und benutz bitte [.CODE] oder [.JAVA] , das ist besser zu lesen.


----------



## Andron (5. November 2007)

Das weiß ich doch.
Ich wollte nur veranschaulichen, wie man an die Tokens ran kommt.
Mit dem counter war ein Beispiel, wenn man nur das dritte Token lesen möchte.


----------



## Thomas Darimont (5. November 2007)

Hallo,

warum so kompliziert? Statte alle deine "Variablen" einfach mit einem entsprechenden Präfix aus ($,#) und dann nimmst du alle alphanumerischen Zeichenfolgen die darauf folgen als Variablennamen...

Schau mal hier:

```
/**
 * 
 */
package de.tutorials;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

/**
 * @author Thomas.Darimont
 *
 */
public class VariableExtractionExample {

  /**
   * @param args
   */
  public static void main(String[] args) throws Exception{
    
    String formula = "($a+$b32a*$cS_W12)*2";
    
    System.out.println(Arrays.toString(extractVariablesFrom(formula)));
    
    ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("javascript");
    Bindings bindings = scriptEngine.createBindings();
    bindings.put("$a", 2);
    bindings.put("$b32a", 3);
    bindings.put("$cS_W12", 4);
    
    System.out.println(scriptEngine.eval(formula, bindings));

  }

  private static String[] extractVariablesFrom(String formula) {
    List<String> variables = new ArrayList<String>();
    
    Matcher matcher = Pattern.compile("(\\$[\\w\\d_]+)").matcher(formula);
    while(matcher.find()){
      variables.add(matcher.group());
    }
    
    return variables.toArray(new String[0]);
  }

}
```

Gruß Tom


----------



## magic_halli (6. November 2007)

Hi,

so, nach ewigem gemache und getue habe ich mir nun überlegt, dass ich mit einem StringTokenizer erstmal den Eingangsstring an gewissen Zeichen in einzelne Tokens zerlege. (das t erstmal)
Nun will ich diejenigen Tokens mit einem Wert ersetzen, die mit dem Suchwort übereinstimmen und auch noch die gleiche Länge wie das Suchwort haben. Somit würde z.B. sigma_v nicht ersetzt werden, weil es nicht die gleiche Länge hat, wie mein Suchwort.
Nur habe ich noch ein Problem: Wie bekomme ich dann wieder meinen Originalstring aus den einzelnen Tokens (veränderte und unveränderte) plus die originalen Zeichensetzungen zusammengesetzt?


```
String str = "sigma_v=sqrt(sigma^2+3*tau^2)";
String search = "sigma";
StringTokenizer tk = new StringTokenizer(str, "+ - * / ( ) ^ =");
int laenge = search.length();
			
while (tk.hasMoreTokens()){
     String tokens = tk.nextToken();
     int laenge_tokens = tokens.length();

     if(laenge == laenge_tokens){
          tokens = "XXX";
     }
}
//wie den Originalstring wieder zusammensetzen?
```

Danke und Gruß

PS: Ich hab nun mittlerweile soviel probiert, dass ich nunmehr keine andere Möglichkeit mehr sehe, wie ich irgendwelche 'Variablen'-Worte in einem STring korrekt ersetzen kann. (also sigma ersetzen, aber sigma_v unberührt lassen, wenn das Suchkriterium nach sigma-Übereinstimmung sucht)


----------

