Plausibilität der Commandlineparameter prüfen

Rund um die LCL und andere Komponenten
Antworten
ABoehlke
Beiträge: 13
Registriert: Do 24. Jul 2008, 17:13

Plausibilität der Commandlineparameter prüfen

Beitrag von ABoehlke »

Hallo Zusammen,

ich versuche mit Hilfe der Unit-RegExpr aus Lazarus 2.0.10 bzw. FPC 3.2.0 eine Plausibilitätsprüfung der per Commandline übergebenen Parameter durchzuführen.
Ziel soll es sein auf gültige Kombinationen der implementierten Optionen/Commandline-Switches zu prüfen unabhängig von der angegebenen Reihenfolge.
Es wird zum Start des Programms mittels CheckOptions bereits auf gültige Optionen geprüft.

Ich habe entweder das richtige handling von Strings nicht gefunden oder nicht verstanden :-(
Natürlich habe ich bereits einige Tutorials in Bezug auf die Verarbeitung von Strings durchstöbert, komme aber nicht weiter.

Hat evtl. jemand eine Lösung oder einen Denkanstoß für mich?



Meine Anforderung
=============

Gültige Optionen sind:
(-m, --multi), (-h, --help) , (-v, --version), (--console), (-i, --install), (-r, --run), (-u, --uninstall), (-c, --config), (--stop)

Gültige Kombinationen:
-i setzt -r voraus schließt aber mindesten --stop aus
-m setzt (-i und-r) oder (-r und --console) voraus
-i erlaubt zusätzlich -m und/oder -c, aber nicht -h und/oder --console und setzt -r voraus

Ich weiß das es durchaus noch weiter Kombinationen gibt die es gilt zu prüfen. Ich denke aber mit der Lösung der genannten Kombinationen sollte ich das dann auch selbst entsprechend anpassen können.

Mit diesem Beispielprogramm habe ich getestet:

Code: Alles auswählen

program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this }
  ,SysUtils, RegExpr;

var
  RegExprObj: TRegExpr;
  Expr, Cmdl: String;

begin
  RegExprObj:= TRegExpr.Create;
  writeln;
  Writeln(Format('  RegExpr-Version = %d.%d', [RegExprObj.VersionMajor, RegExprObj.VersionMinor]));
  writeln;
  Expr:= '.*(-i)(-r).*';
  Cmdl:= 'project1.exe -i -r';
  writeln('  Expression: '+ Expr);
  writeln('  Commandline: '+ Cmdl);
  RegExprObj.Expression:= Expr;
  if RegExprObj.Exec(Cmdl) then
    writeln('OKAY') else WriteLn('Not OKAY');
  RegExprObj.Free;
end.
Ausgabe von project1.exe

Code: Alles auswählen

C:\examples\RegExpr>project1

  RegExpr-Version = 0.987

  Expression: .*((-i)(-r)(?!--stop)).*
  Commandline: project1.exe -i -r
An unhandled exception occurred at $0042B12A:
ERegExpr: TRegExpr compile: unrecognized modifier (pos 20)
  $0042B12A
  $00427BCA
  $0042693B
  $0042693B
  $004259A2
  $00429BFB
  $00401839  main,  line 27 of project1.lpr
Auch wenn ich in obigem Beispiel auf den Ausschluß von "--stop" verzichte ist zwar die Exception weg, aber das Ergebnis trotzdem nicht richtig.

Code: Alles auswählen

C:\examples\RegExpr>project1

  RegExpr-Version = 0.987

  Expression: .*((-i)(-r)).*
  Commandline: project1.exe -i -r
Not OKAY

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von Winni »

Hi!

Mal wieder eine Möglichkeit für die so oft unterschätzen Sets:

* strip die '-' und '--' weg

* Nimm jeweils den ersten Buchstaben und füge ihn einem Set hinzu:

Code: Alles auswählen

Type setofchar = Set of Char;

var MySet : setofchar;
..
MySet := [];
...
Include (Myset, ParameterChar);
.....
Und dann kannst Du logische if oder case Abfragen machen:

Code: Alles auswählen

if ('i' in MySet) and ('r' in Myset) then ...

So würde ich das machen.

Winni

ABoehlke
Beiträge: 13
Registriert: Do 24. Jul 2008, 17:13

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von ABoehlke »

Das geht in diesem Fall leider nicht so einfach.
In Deinem Ansatz gibt es eine Kollision zwischen (-c, --config) und (--console)

Außerdem sollte dies auch mein Einstieg ind RegEx(RegExpr) werden. :-)

Ich habe zwischenzeitlich einen Ansatz gefunden.

Code: Alles auswählen

RegEx: ((?=.*--install|.* -i)(?=.*--run|.* -r)(?!.*--console))
Diesen habe ich mit Unittests auf https://regex101.com verifiziert.

Allerdings stehe ich nun vor dem Bereits erwähnten Problem:

C:\examples\RegExpr>project1.exe

RegExpr-Version = 0.987

Expression: ((?=.*--install|.* -i)(?=.*--run|.* -r)(?!.*--console))
Commandline: project1.exe -i -r
An unhandled exception occurred at $0042B12A:
ERegExpr: TRegExpr compile: unrecognized modifier (pos 21)
$0042B12A
$00427BCA
$0042693B
$0042693B
$004259A2
$00429BFB
$00401839 main, line 27 of project1.lpr

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von Winni »

ABoehlke hat geschrieben:
Mo 19. Apr 2021, 20:40
Das geht in diesem Fall leider nicht so einfach.
In Deinem Ansatz gibt es eine Kollision zwischen (-c, --config) und (--console)

Außerdem sollte dies auch mein Einstieg ind RegEx(RegExpr) werden. :-)
Hi

Also das erste Problem ist ja nun keins: Musst du aus --console ein 'k' machen.

Aber wenn Du es lieber kompliziert mit RegEx machen möchtest - da würde ich mir zum Einstieg was Einfacheres aussuchen.

Winni

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von Socke »

ABoehlke hat geschrieben:
Mo 19. Apr 2021, 20:40
Ich habe zwischenzeitlich einen Ansatz gefunden.

Code: Alles auswählen

RegEx: ((?=.*--install|.* -i)(?=.*--run|.* -r)(?!.*--console))
Diesen habe ich mit Unittests auf https://regex101.com verifiziert.
Die von Free Pascal mitgelieferten Units sind leider nicht ganz so mächtig wie andere Bibliotheken. Daher kannst du hier schon eimal auf nicht unterstützte Modifikatoren etc. stoßen.
Ich würde jede Option einzeln prüfen und deren Vorhandensein speichern. Die Verifikation kannst du dann in klassischer Programmlogik durchführen und im Fehlerfalle eine aussagekräftige Meldung anzeigen. Bei regulären Ausdrücken muss man sich meist auf ein "passt nicht" reduzieren, da die RegEx nur sagt, dass der gesamte Ausdruck nicht gefunden wurde, aber nicht ausgibt, was fehlt bzw. falsch ist.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

ABoehlke
Beiträge: 13
Registriert: Do 24. Jul 2008, 17:13

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von ABoehlke »

Vielen Dank für Eure Unterstützung und hilfreichen Hinweise.

Ich werde noch etwas die Dokumentationen zu den Units studieren, bringt es mich dann ja doch auch etwas tiefer in die Möglichkeiten von RegEx und im speziellen der von FPC mitgelieferten Implementierungen.

Danke und bis bald mal wieder.

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von charlytango »

ABoehlke hat geschrieben:
Di 20. Apr 2021, 09:24
Ich werde noch etwas die Dokumentationen zu den Units studieren, bringt es mich dann ja doch auch etwas tiefer in die Möglichkeiten von RegEx und im speziellen der von FPC mitgelieferten Implementierungen.
bin etwas erstaunt, liegt aber vielleicht an meiner Abneigung von regex mangels Routine.
Ist das nicht etwas wie mit Kanonen aus Spatzen scheißen?

Hier geht es ganz ohne regex:
https://wiki.lazarus.freepascal.org/Com ... _variables

Parameter in einer Schleife abfragen, Testen (also Prüflogiken einbauen) und Meldungen schreiben.

Benutzeravatar
Roland Chastain
Beiträge: 156
Registriert: Sa 7. Jul 2012, 21:50
Wohnort: Saargemünd
Kontaktdaten:

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von Roland Chastain »

Hallo!

Wenn ich richtig verstanden habe, was du machen willst, und wenn Sie wirklich reguläre Ausdrücke verwenden möchten, vielleicht könnte so etwas funktionieren:

Code: Alles auswählen

  HasOptI, HasOptR, HasOptM: boolean;
begin
  { ... }
  
  RegExprObj.Expression:= '\s(-i|--install)(\s|$)';
  HasOptI := RegExprObj.Exec(Cmdl);
  
  RegExprObj.Expression:= '\s(-r|--run)(\s|$)';
  HasOptR := RegExprObj.Exec(Cmdl);
  
  RegExprObj.Expression:= '\s(-m|--multi)(\s|$)';
  HasOptM := RegExprObj.Exec(Cmdl);
  
  // Oder kürzer:
  
  HasOptM := ExecRegExpr('\s(-m|--multi)(\s|$)', Cmdl);
  
  // (\s|$) = Ein Leerzeichen oder das Ende der Zeichenfolge
  
Viele Grüße.

Roland
Petit poisson deviendra grand,
Pourvu que Dieu lui prête vie.

BeniBela
Beiträge: 309
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von BeniBela »

Für sowas habe ich einen CommandLineReader gebaut.

Der kann dann auch gleich eine Hilfe ausgeben, wenn ein Parameter falsch ist

ABoehlke
Beiträge: 13
Registriert: Do 24. Jul 2008, 17:13

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von ABoehlke »

Zum Abschluss noch ein paar Informationen aus meinen Untersuchungen zu RegEx zu diesem Thema.

Leider unterstützen die von FPC genannten Implementierungen zu "Regular Expressions" keine lookaheads.
Diese sind die Voraussetzung für den von mir angedachten Ausdruck "((?=.*--install|.* -i)(?=.*--run|.* -r)(?!.*--console))"
Mit diesem, war meine Überlegungung, könnte mit nur einer Abfrage (if not RegExpr then Except) die Plausibilität geprüft werden.

Ich denke das war's mit meinem ersten Ausflug in den Bereich der "Regular Expressions", diesmal.
Ich werde es dann doch mit geignetem Programcode lösen.

Danke noch einaml für Eure Unterstützung und Anregungen.

sstvmaster
Beiträge: 576
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Plausibilität der Commandlineparameter prüfen

Beitrag von sstvmaster »

Und sowas:

Code: Alles auswählen

Expr:= '((\s--install|\s-i)|(\s--run|\s-r)|(!\s--console))'; 
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Antworten