Améliorations des fonctions de lignes de commandes : gestion des options et des chaînes entre guillemets...

Description

Définition :
- Une option est un argument de ligne de commande qui commence par un caractère spécial :
- '-' ou '/' sous Windows
- '-' sous linux
- cette option peut être suivi d'une valeur collée à l'option ou séparée par un caractère quelconque (par ex : ':')
- Un paramètre est un argument qui n'es pas une option
- J'entends par guillemet, tout caractère pouvant servir de délimitation pour une chaîne de caractères (par ex :'"', ''', '`') contenant le caractère de séparation d'argument (par ex : ' '). Par ex : pour mettre un guillemet dans une chaîne entre guillemet, il doit être doublé.

Ce code permet de tester si une option se trouve dans la ligne de commande et de renvoyer sa valeur même si c'est une chaîne entre guillemets contenant des guillemets. Il permet aussi de compter le nombre d'options.

La fonction ParamStr remplace celle existante et permet de renvoyer des chaînes entre guillemets même si elle contiennent des guillemets.

La fonction GetOptionCount renvoie le nombre d'option dans la ligne de commande

La fonction GetOptionValue renvoie (en paramètre) la valeur d'une option

exemple de ligne de commande : '-W3 -G 5 /OPTION:valeur -OPTION2="valeur" """C:\azerty.exe"" %1" paramètre3 paramètre4'

Source / Exemple :


unit uCmdLine;

interface

uses SysUtils;

// renvoie le indexième paramètre
function ParamStr(Index: Integer; chQuotation: Char = '"';chParamSeparator: Char = ' '): String; forward;
// renvoie la valeur d'un paramètre
function GetOptionValue(const strOptionName: string; OptionChars: TSysCharSet; var strValue: String;
                        chSeparator: Char = ':';chQuotationMark: Char = '"';chParamSeparator: Char = ' '): Boolean; forward;
// renvoie le nombre d'option dans la ligne de commande
function GetOptionCount(OptionChars: TSysCharSet): Cardinal; forward;

implementation

uses StrUtils;

//******************************************************************
// par le terme guillemet,                                         *
// j'entends toute marque de délimitation de chaine de caractère   *
// comme " ou ' ou ` (ou pourquoi pas /)                           *
//******************************************************************
// remplace la fonction ParamStr pour gérer les guillemets         *
// tout guillemet dans une chaîne entre guillemets doit être doublé*
//=================================================================*
// Index : numéro (à partir de 0) du paramètre à renvoyer          *
// chQuotation : caractère servant de délimitation de chaîne       *
// chParamSeparator : séparateur de paramètres                     *
//******************************************************************
function ParamStr(Index: Integer; chQuotation: Char = '"';chParamSeparator: Char = ' '): String;
var
  // compteur, index du premier caractère du paramètre précédent
  i,prevArg: Integer;
  // taille de la ligne de commande
  cbCmdLine: Integer;
  // nombre d'espace, de guillemets
  cntSpace, cntQuotationMark: Integer;
begin
  // si l'index est au dessus du nombre de paramètres
  if Index > ParamCount then
    Exit;

  // on demande la taille de la ligne de commande
  cbCmdLine := Length(CmdLine);

  // initialisation des variables
  cntSpace := 0;
  cntQuotationMark := 0;
  prevArg := 0;

  // pour chaque caractère dans la ligne de commande
  for i := 0 to cbCmdLine - 1 do
  begin
    // si le caractère actuel est un guillemet
    if CmdLine[i] = chQuotation then
      // on incrémente le compteur
      cntQuotationMark := cntQuotationMark + 1;

    // si le caractère actuel est un espace
    if CmdLine[i] = chParamSeparator then
    begin
      // si on ne se trouve pas dans une chaîne guillemettée
      if (cntQuotationMark mod 2) = 0 then
      begin
        // si la nombre d'espace correspond au paramètre demandé
        // premier paramètre : cntSpace = 0
        if cntSpace = Index then
        begin
          // on copie le paramètre à partir de l'espace précédent jusqu'ici
          Result := Copy(CmdLine,prevArg+1,i-prevArg);
          // on supprime les doubles guillemets : tout guillemet dans une chaîne guillemettée doit être doublée
          Result := AnsiReplaceStr(Result,chQuotation+chQuotation,chQuotation);
          // on renvoie la valeur
          Exit;
        end
        // si ce n'est pas le paramètre numéro Index
        else
        begin
          // incrémente le nombre d'espace
          cntSpace := cntSpace + 1;
          // enregistre la position du début du paramètre actuel
          prevArg := i + 1;
        end;
      end;
    end;
  end;
  //si on arrive ici
  // c'est que l'on doit copier le dernier paramètre
  Result := Copy(CmdLine,prevArg+1,i-prevArg);
  Result := AnsiReplaceStr(Result,chQuotation+chQuotation,chQuotation);
end;

// renvoie le paramètre associé à l'option strOptionName
// (par ex : /EXT:.txt renvoie .txt)
//========================================================================================
// strOptionName : nom de l'option à rechercher (par ex : EXT)
// OptionChars : premier caractère d'une option : ['/','-'] pour Windows, ['-'] pour Linux
// strValue : renvoie la valeur de l'option s'il l'option existe et a une valeur
// chSeparator : caractère séparateur entre l'option et sa valeur (#0 indique aucun caractère) (par ex : ':')
// chQuotationMark : caractère servant de délimitation de chaîne
// chParamSeparator : séparateur de paramètres
// renvoie False si l'option n'existe pas, True sinon
function GetOptionValue(const strOptionName: string; OptionChars: TSysCharSet; var strValue: String;
                        chSeparator: Char = ':';chQuotationMark: Char = '"';chParamSeparator: Char = ' '): Boolean;
  var
    // compteur
    i : Integer;
    // chaine du paramètre
    strParam: String;
    // position du séparateur
    posSeparator: Integer;
  begin
    // pour chaque paramètre dans la ligne de commande
    for i := 0 to ParamCount do
    begin
      // on demande le paramètre d'index i
      strParam := ParamStr(i,chQuotationMark,chParamSeparator);
      // si la premier caractère du paramètre est un des caractères d'option
      // et que le nom de l'option se trouve à partir du deuxième caractère
      if (strParam[1] in OptionChars) and (Pos(strOptionName,strParam) = 2) then
      begin
        // si la valeur n'est pas séparée de l'option
        if chSeparator = #0 then
        begin
          // elle se trouve après le caractère d'option et l'option
          posSeparator := Length(strOptionName) + 1;
        end
        // si le caractère de séparation est celui de séparation de paramètre
        else if chSeparator = chParamSeparator then
        begin
          // la valeur se trouve dans le paramètre suivant
          posSeparator := 0;
          strValue := ParamStr(i+1,chQuotationMark,chParamSeparator);
        end
        else
          // on récupère la position du séparateur option/valeur
          posSeparator := Pos(chSeparator,strParam);
        
        // si pas de spérateur
        if posSeparator = 0 then
        begin
          // renvoie True : option trouvé sans valeur
          Result := True;
        end
        // sinon séparateur trouvé
        else
        begin
          // renvoie True : option trouvée avec valeur
          Result := True;
          // on copie la valeur de l'option
          strValue := Copy(strParam,posSeparator + 1,Length(strParam) - posSeparator);
          // si l'option est entre guillemets
          if (strValue[1] = chQuotationMark) and (strValue[Length(strValue)] = chQuotationMark) then
            // on les retirent
            strValue := Copy(strValue,2,Length(strValue)-2);
        end;
        // on n'a plus besoin de chercher
        Break;
      end;
    end;
    // si on arrive ici : on a parcouru tous les paramètres
    // et l'option recherchée n'a pas été trouvée
    Result := False;
  end;

// renvoie le nombre d'option dans la ligne de commande
// OptionChars : premier caractère d'une option : ['/','-'] pour Windows, ['-'] pour Linux
// chSeparator : caractère séparateur entre l'option et sa valeur (par ex : ':')
// chQuotationMark : caractère servant de délimitation de chaîne
function GetOptionCount(OptionChars: TSysCharSet): Cardinal;
  var
    // compteur
    i : Integer;
    // chaine du paramètre
    strParam: String;
  begin
    // initialisation
    Result := 0;
    // pour chaque paramètre dans la ligne de commande
    for i := 0 to ParamCount do
    begin
      // on demande le paramètre d'index i
      strParam := ParamStr(i);
      // si la premier caractère du paramètre est un des caractères d'option
      if (strParam[1] in OptionChars) then
        // on incrémente le nombre d'options
        Result := Result + 1;
    end;
  end;
end.

Conclusion :


Tester avec Delphi 6

N'hésitez pas à commenter et à noter...

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.