2016-05-03 3 views
0

ich eine Textdatei mit SQL-Befehlen haben, ich habe einige Code getan „ignorieren“, um die Kommentare und Leerzeichen in orde nur die Befehle zu bekommen (ich werde schreiben Code unten und ein Beispiel für die Textdatei und Ausgabe), das funktioniert gut, aber in dieser Textdatei habe ich auch Zeilen wie diese "--------------------- -------------- "das muss ich ignorieren, ich habe den Code gemacht, um es zu ignorieren, aber ich kann nicht herausfinden, warum es nicht richtig funktioniert. Code:Auslassen von Linien mit Bindestrichen in einer Textdatei mit Regex in C#

public string[] Parser(string caminho) 
{ 
      string text = File.ReadAllText(caminho); 
      var Linha = Regex.Replace(text, @"\/\**?\*\/", " "); 
      var Commands = Linha.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries) 
       .Where(line => !string.IsNullOrWhiteSpace(line)) 
       .Where(line => !Regex.IsMatch(line, @"^[\s\-]+$")) 
       .ToArray(); 
} 

Dies ist die .Where Ich habe die gestrichelten Linien zu "ignorieren":

.Where (line => Regex.IsMatch (Linie, @ "^ [\ s -] + $ "))


Probe von Text mit den Strichen:

/ 

--------------------------------------------------------------------- 

UPDATE CDPREPORTSQL 
SET COMANDOSQL_FROM = 
'SELECT DESCONTO,EMPCOD,EMPDSC,LINVER,NOMESISTEMA,OBS,ORCCOD,ORCVER,PEDCOD,PEDDSC, 
ROUND(PRCUNIT*#CAMBIO#,5) PRCUNIT, 
ROUND(PRCUNITSEMDESC*#CAMBIO#,5) PRCUNITSEMDESC, 
PROPCHECK,QTDGLOB,QTDPROP,REFCOD,REFDSC,EMPCODVER, COEFGERAL_PLT FROM #OWNER#.VW_PROPOSTAS', 
COMANDOSQL_WHERE = 
'WHERE ORCCOD=#ORCCOD# AND ORCVER=#ORCVER# AND NOMESISTEMA=#NOMESISTEMA# AND PEDCOD=#MYCOD#' 
WHERE REPID = 'CDP0000057' 
/

--------------------------------------------------------------------- 

Probe des Ausgangs:

--------------------------------------------------------------------- 

UPDATE CDPREPORTSQL 
SET COMANDOSQL_FROM = 
'SELECT DESCONTO,EMPCOD,EMPDSC,LINVER,NOMESISTEMA,OBS,ORCCOD,ORCVER,PEDCOD,PEDDSC, 
ROUND(PRCUNIT*#CAMBIO#,5) PRCUNIT, 
ROUND(PRCUNITSEMDESC*#CAMBIO#,5) PRCUNITSEMDESC, 
PROPCHECK,QTDGLOB,QTDPROP,REFCOD,REFDSC,EMPCODVER, COEFGERAL_PLT FROM #OWNER#.VW_PROPOSTAS', 
COMANDOSQL_WHERE = 
'WHERE ORCCOD=#ORCCOD# AND ORCVER=#ORCVER# AND NOMESISTEMA=#NOMESISTEMA# AND PEDCOD=#MYCOD#' 
WHERE REPID = 'CDP0000057' 


--------------------------------------------------------------------- 

Dies sind die Beispiele für Aussagen, die auftreten können, und dass ich zu verarbeiten:

/* */ 
      UPDATE Orc 
/*UPDATE comando */ 
set MercadoInt = 'N', Coef_KrMo = 1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL 
/

Ein anderes:

/* */ 
---- comment 
      UPDATE Orc set MercadoInt = 'N', Coef_KrMo = 
      -1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL 
/

Und noch eins:

/* */ 
      UPDATE Orc set MercadoInt = 'N', Coef_KrMo = 1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL 
/

Bitte beachte, dass ich brauche sie auch zu verarbeiten, wenn es Abschnitt in der Mitte, wenn die Aussage Beachten Sie, dass alles andere funktioniert (es „ignoriert“ die Kommentare und Leerzeichen)

kommentiert werden die ‚/‘ ist nur zu teilen, die Befehle in der Textdatei

+0

Dies kann leicht komplexer werden, als ein Regex im Allgemeinen bewältigen kann, wenn Sie auf die gleiche Weise wie SQL kommmentieren müssen. Z.B. Eine Zeile, die Bindestriche enthält, kann ein perfekt gültiges Eingabeelement sein, wenn sie als Teil eines mehrzeiligen Zeichenfolgenliterals auftritt. –

+0

Also sagen Sie, dass diese Methode in einigen Fällen unwirksam sein kann? Was sollte der beste Ansatz sein, ohne Software oder Add-Ons von Drittanbietern zu verwenden? Plus, für das, was ich weiß, die Befehle werden nicht viel davon abweichen –

+0

@Damien_The_Unbeliever, wenn Sie brauchen, kann ich einen Link auf die Volltext-Datei für Sie einen Blick auf es –

Antwort

0

Der folgende Code arbeitet an den Beispielen, die Sie gaben.

private const string DashComment = @"(^|\s+)--.*(\n|$)"; 
    private const string SlashStarComment = @"\/\*.*?\*\/"; 
    private string[] CommandSplitter(string text) 
    { 
     // strip /* ... */ comments 
     var strip1 = Regex.Replace(text, SlashStarComment, " ", RegexOptions.Multiline); 
     var strip2 = Regex.Replace(strip1, DashComment, "\n", RegexOptions.Multiline); 
     // split into individual commands separated by '/' 
     var commands = strip2.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); 

     return commands.Where(line => !String.IsNullOrWhiteSpace(line)) 
      .ToArray(); 
    } 

Ich nahm die drei Beispiele, die Sie in Ihrer Frage gestellt und sie in einer einzigen Zeichenfolge setzen. Es sieht wie folgt aus (ja, es ist hässlich):

 private const string Test1 = @"/* */ 
      UPDATE Orc 
/*UPDATE comando */ 
set MercadoInt = 'N', Coef_KrMo = 1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL 
/
/* */ 
---- comment 
      UPDATE Orc set MercadoInt = 'N', Coef_KrMo = 
      -1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL 
/
/* */ 
      UPDATE Orc set MercadoInt = 'N', Coef_KrMo = 1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N', Arred_NDecs = 0 WHERE MercadoInt IS NULL 
/"; 

Dann rief ich die CommandSplitter:

var result = CommandSplitter(Test1); 

Und die Ergebnisse Ausgabe:

foreach (var t in result) 
{ 
    Console.WriteLine(t); 
    Console.WriteLine("////////////////////////"); 
} 

, dass die /* ... */ Kommentare entfernt und die -- ... Kommentare.

Es arbeitete auch an diesem Beispiel:

private const string Test2 = 
     "Update Orc set /* this is a comment */ MercadoInt = 'N' -- this is another comment\n" + 
     "Where MercadoInt is NULL --another comment"; 

Der Ausgang:

Update Orc set MercadoInt = 'N' 
Where MercadoInt is NULL 

aktualisieren Der obige Code eine Reihe von Befehlen zurückgibt. Jeder Befehl besteht aus mehreren Zeilen. Wenn Sie überflüssige Leerzeichen am Anfang von Zeilen entfernen und leere Zeilen entfernen möchten, müssen Sie jeden einzelnen Befehl separat verarbeiten. So würden Sie die CommandSplitter wie diese erweitern wollen:

private string[] CommandSplitter(string text) 
{ 
    // strip /* ... */ comments 
    var strip1 = Regex.Replace(text, SlashStarComment, " ", RegexOptions.Multiline); 
    var strip2 = Regex.Replace(strip1, DashComment, "\n", RegexOptions.Multiline); 
    // split into individual commands separated by '/' 
    var commands = strip2.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 

    return commands.Select(cmd => cmd.Split(new[] {'\n'}) 
     .Select(l => l.Trim())) 
     .Select(lines => string.Join("\n", lines.Where(l => !string.IsNullOrWhiteSpace(l)))) 
     .ToArray(); 
} 
+0

sie sagten, dass mein Code würde nicht funktionieren, weil Situationen einige Abschnitte in der Mitte der Anweisung wie folgt kommentierte: 'UPDATE Orc festgelegt MercadoInt = 'N', Coef_KrMo = -1, Coef_KrMt = 1, Coef_KrEq = 1, Coef_KrSb = 1, Coef_KrGb = 1, Coef_MDEmp = 1, Coef_MDLoc = 1, Abrv_MDLoc = '', Dsc_MDLoc = '', Arred_MDLoc = 'N ', Arred_NDecs = 0 WHERE MercadoInt IST NULL' –

+0

Jim Ich werde meine Frage mit Beispielen aktualisieren, die sie mir zum Testen gaben, also wenn meine dll kann die Anweisungen so verarbeiten, dass ich denke, dass ich in Ordnung bin. Bitte beachten Sie die bearbeitete Frage –

+0

@ Mr.Toxy: Siehe meine aktualisierte Antwort. –

0

von dem, was ich verstehe, haben Sie eine Textdatei mit mehreren SQL-Befehle, getrennt durch:

/ 

--------------------------------------------------------------------- 

Und Sie wollen nur den Text zwischen diesen Strichen. Wenn ja, warum nicht den Text mit Regex.Split teilen, dann raus alle Elemente?

This Regex scheint zu funktionieren:

\/\n\n-+ 

auf der Regex.Split Dokumentation Basierend würde der Code sein:

string input = File.ReadAllText(caminho); 
string pattern = "\/\n\n-+";    

string[] substrings = Regex.Split(input, pattern); 
foreach (string match in substrings) 
{ 
    //do cool stuff with your cool query 
} 
+0

es ist fast das xD Ich habe die Befehle getrennt durch '/'Die gestrichelten Linien sind einfach ohne Grund da.Es war nicht ich, wer diese Dateien kompiliert hat und ich kann nicht ändern, ich muss sie behandeln, wie sie sind. Summing Dinge die Befehle sind durch "/" getrennt, die Bindestriche sind nur Rubel, die ignoriert werden müssen –

+0

Sie meinen, dass die '/' sind die Trennzeichen, die immer da sind, aber die Zeilen von ---- aren ' t immer präsent? Also gibt es auch so einen Input? '/ sqlquery/sqlquery' – ohyeah

+0

ja das '/' ist der Trenner und die Zeilen von ----- sind nicht immer da. Hier erhalten Sie einen Link zur Volltextdatei: https://drive.google.com/file/d/0B1xc1ft-s78NTHdZdlpTTWlfLVE/view?usp=sharing –

0

Wenn Sie regex nicht verwenden möchten Sie auch nutzen könnten !line.TrimStart().StartWith("-") sollte das gleiche sein und ich denke es ist schneller.

+0

Ich habe so etwas versucht: ' line.Substring (line.IndexOf ('-') , line.LastIndexOf ('-')). Länge <1' Aber es funktioniert nicht –

+0

funktioniert der Split wirklich? In der oberen Zeile ersetzen Sie das geteilte Zeichen durch "" - (Ich bin kein Regex-Experte) –

+0

ja der Split funktioniert wirklich hier ist ein Link zur Ausgabe Textdatei mit den Befehlen https://drive.google.com/file/d/0B1xc1ft-s78NVWFtdi1YUXF3YXc/view? usp = sharing > Die Datei kann nicht in Laufwerk geöffnet werden Ich weiß nicht warum, downloaden Sie es daher können Sie mit der "alten" Datei vergleichen. Sie werden sehen, dass der Split funktioniert, aber die gestrichelten Linien mit dem obigen Code sind immer noch outputed –

-1

Ich habe den Code wie dies getan, so weit gut funktioniert.

public string[] Parser(string caminho) 
     { 
      List<string> Commands2 = new List<string>(); 
      string text = File.ReadAllText(caminho); 
      var Linha = Regex.Replace(text, @"\/\**?\*\/", " "); 
      var Commands = Linha.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries) 
       .Where(line => !string.IsNullOrWhiteSpace(line)) 
       .Where(line => !Regex.IsMatch(line, @"^[\s\-]+$")) 
       .ToArray(); 


      Commands2 = Commands.ToList(); 


      for(int idx = 0; idx < Commands2.Count; idx ++) 
      { 

       if (Commands2[idx].TrimStart().StartsWith("-")) 
       { 
        string linha = Commands2[idx]; 
        string linha2 = linha.Remove(linha.IndexOf('-'), linha.LastIndexOf('-') - 1); 
        Commands2[idx] = linha2; 
       } 



      } 
      //test the output to a .txt file 
      StreamWriter Comandos = new StreamWriter(Directory.GetParent(caminho).ToString() + "Out.txt", false); 
      foreach (string linha in Commands2) 
      { 
       Comandos.Write(linha); 
      } 
      Comandos.Close(); 
      return Commands2.ToArray(); 
     } 

Nachdem sie meinen Code analysiert, sagte sie, dass ich das nicht (oben erwähnt als ) verwenden können, weil es wird nicht für einige Fälle wie Kommentare in die Mitte der Aussagen arbeiten. Ich versuche es jetzt mit Tsql120Parser

+0

Wenn jemand eine Methode hat, die besser als diese funktioniert, sagen Sie bitte: D –

0

All dies scheint ziemlich komplex und langsam. Wenn Sie nur wollen, finden/ablehnen gestrichelten Linien, warum nicht verwenden:

if (line.StartsWith("----")) 

(Unter der Annahme, dass 4 Striche ausreichend sind, solche Linien eindeutig zu erkennen)

Wenn es zu Beginn der Leer sein kann Linie, dann:

if (line.Trim().StartsWith("----")) 

ist nicht nur dieser Ansatz unendlich besser lesbar als regex, wird es höchstwahrscheinlich viel schneller sein.

+0

Es ist etwas komplizierter als das. Es gibt zwei Arten von Kommentaren: solche, die mit '/ *' beginnen und mit '* /' enden und mehrere Zeilen (wie C# -Blockkommentare) abdecken können, und solche, die mit '--' beginnen und bis zum Ende der Zeile gehen Zeile (wie C# '//' Kommentare). Er möchte sie beide ausziehen. –

+0

Das Auffinden von/* und dann das Überspringen von Text, bis Sie ein */drücken, ist ein triviales Analyseproblem. Wie findet man // und schneidet die aktuelle Zeile ab. Obwohl eine Regex diese Dinge tun kann, gibt es einfachere Ansätze, die besser funktionieren. Ich bevorzuge lesbaren/wartbaren Code, der schnell zu unlesbarem Code führt, der langsamer ist. Es lohnt sich immer, die Frage zu stellen. Löse ich dieses Problem auf die richtige Art und Weise? (Und es ist in Ordnung für die Antwort ja manchmal zu sein und keine anderen Zeiten, solange wir immer die Frage von uns selbst stellen) –

+0

@JasonWilliams Jim hat Recht Ich muss beide Arten von Commants und das Metho, das ich wähle, "ignorieren" muss auch funktionieren, wenn ein Kommentar in der Mitte der Anweisung steht wie SELECT Name, Alter /, * E-Mail, Adresse */FROM tbl_Client WHERE .... –

Verwandte Themen