Inno Setup - 整数或设置/范围通配符?

时间:2016-01-28 03:09:19

标签: inno-setup pascalscript

我需要一个只匹配数字的通配符。我试过这个:

FileExistsWildcard(ExpandConstant('{app}\sav[1-9]'))

但帕斯卡显然不会这样做。是否有这样的通配符或者我应该编写自定义函数还是什么?

P.S。是否有Inno Setup的通配符匹配列表?

1 个答案:

答案 0 :(得分:1)

The @TLama's FileExistsWildcard function内部使用Inno Setup FindFirst function,而内部使用Windows FindFirstFile function

Windows在其通配符中仅支持getline(cin, userCommand); *。范围/设置模式?仅为* nix。

所以这不是Pascal限制,而是Windows限制。

实现支持所有[a-z]?*的通用匹配功能并不容易。

我尝试实现与Windows匹配([a-z])兼容的匹配函数,但支持设置模式(包括范围集)。

我没有确定Windows如何在掩码和文件名中处理FindFirstFile的确切规则。所以我的匹配函数在这方面的表现并不完全相同。否则,我相信,它是完全相同的。并且支持.设置模式以及范围设置模式[abc],或[a-z]之类的任何组合。

[_0-9a-z]

使用它像:

function MatchesMaskEx(Mask: string; FileName: string): Boolean;
var
  MaskI: Integer;
  MaskC: Char;
  FileNameI: Integer;
  FileNameI2: Integer;
  P: Integer;
  Mask2: string;
  EOSMatched: Boolean;
begin
  Mask := LowerCase(Mask);
  FileName := LowerCase(FileName);

  MaskI := 1;
  FileNameI := 1;
  Result := True;
  EOSMatched := False;

  while (MaskI <= Length(Mask)) and Result do
  begin
    MaskC := Mask[MaskI];

    if MaskC = '?' then
    begin
      { noop, ? matches anything, even beyond end-of-string }
      Inc(FileNameI);
    end
      else
    if MaskC = '[' then
    begin
      if FileNameI > Length(FileName) then
      begin
        Result := False;
      end
        else
      begin
        P := Pos(']', Copy(Mask, MaskI + 1, Length(Mask) - MaskI));

        if  P = 0 then
        begin
          { unclosed set - no match }
          Result := False;
        end
          else
        begin
          Result := False;
          P := P + MaskI;
          Inc(MaskI);
          while (MaskI < P) and (not Result) do
          begin
            MaskC := Mask[MaskI];
            { is it range (A-Z) ? }
            if (MaskI + 2 < P) and (Mask[MaskI + 1] = '-') then
            begin
              MaskI := MaskI + 2;
            end;

            { matching the range (or pseudo range A-A) }
            if (MaskC <= FileName[FileNameI]) and
               (FileName[FileNameI] <= Mask[MaskI]) then
            begin
              Inc(FileNameI);
              Result := True;
              MaskI := P - 1;
            end;
            Inc(MaskI);
          end;
        end;
      end;
    end
      else
    if MaskC = '*' then
    begin
      Mask2 := Copy(Mask, MaskI + 1, Length(Mask) - MaskI);
      Result := False;
      { Find if the rest of the mask can match any remaining part }
      { of the filename => recursion }
      for FileNameI2 := FileNameI to Length(FileName) + 1 do
      begin
        if MatchesMaskEx(
             Mask2, Copy(FileName, FileNameI2, Length(FileName) - FileNameI2 + 1)) then
        begin
          Result := True;
          MaskI := Length(Mask);
          FileNameI := Length(FileName) + 1;
          break;
        end;
      end;
    end
      else
    begin
      if (FileNameI <= Length(FileName)) and (FileName[FileNameI] = MaskC) then
      begin
        Inc(FileNameI);
      end
        else
      begin
        { The dot can match EOS too, but only once }
        if (MaskC = '.') and (FileNameI > Length(FileName)) and (not EOSMatched) then
        begin
          EOSMatched := True;
        end
          else
        begin
          Result := False;
        end;
      end;
    end;

    Inc(MaskI);
  end;

  if Result and (FileNameI <= Length(FileName)) then
  begin
    Result := False;
  end;
end;

根据您的特定需求,您还可以使用简单的特殊功能,例如:

function FileExistsEx(Path: string): Boolean;
var
  FindRec: TFindRec;
  Mask: string;
begin
  if FindFirst(AddBackslash(ExtractFilePath(Path)) + '*', FindRec) then
  begin
    Mask := ExtractFileName(Path);
    try
      repeat
        if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0) and
           MatchesMaskEx(Mask, FindRec.Name) then
        begin
          Result := True;
          Exit;
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end;

  Result := False;
end;

使用它像:

function SpecialFileExists(Path: string): Boolean;
var
  FindRec: TFindRec;
begin
  if FindFirst(AddBackslash(Path) + '*', FindRec) then
  begin
    try
      repeat
        if (Length(FindRec.Name) = 4) and
           (Copy(FindRec.Name, 1, 3) = 'sav') and
           (FindRec.Name[4] >= '0') and (FindRec.Name[4] <= '9') then
        begin
          Result := True;
          Exit;
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end;

  Result := False;
end;