需要 PowerShell 脚本来验证用户输入是否具有有效的 UNIX 路径

need powershell script to validate user input for valid unix path

提问人:Ashar 提问时间:11/12/2023 最后编辑:Ashar 更新时间:11/13/2023 访问量:89

问:

我需要验证用户是否输入了有效的 unix 路径语法,而不是主机上的实际路径。

可以有单个或多个路径,用逗号或空格分隔,并用单引号、双引号或根本不用引号括起来。

下面的 PowerShell 尝试无法验证上述条件:

  - name: Validate Inputs

    run: |

      $inputPaths = "${{ inputs.source_files }}"

      # Check if the input is not empty

      if (-not $inputPaths) {
        echo "Error: 'paths' input is required."
        exit 1
      }

      # Check syntax of each provided path
      $pathsArray = $inputPaths -split ',| '

      foreach ($path in $pathsArray) {

        if (-not ($path -match "^[a-zA-Z]:\\|\\\\|/'[^'\s].*'$|^[a-zA-Z]:\\|\\\\|/\"[^\"\s].*\"$|^[a-zA-Z]:\\|\\\\|/[^'\s]+$")) {
          echo "Error: '$path' is not a valid absolute path syntax."
          exit 1

        }
      }

      echo "Inputs have valid syntax. 

有效输入包括

/tmp/mydir
'/tmp/my  dir1'
"/tmp/my  dir2"
/tmp/mydir '/tmp/my  dir1' '/tmp/my  dir2'
'/tmp/my  dir1','/tmp/my  dir2'

无效的输入:

'/tmp/my  dir1,/tmp/my  dir2'
/tmp/my  dir1
'/tmp/my  dir1
/tmp/my  dir1'

我尝试验证报价,但它在有效报价上出错:

$paths = "'/u/marsh/UNX/scripts/testscript/test_maillist.txt' '/pathx with space/file1' '/path,with,commas/file2' ""/double quoted path/file3"" ""/path with space/file4"" 'single quoted path/file5' /pathx with space/file1"

# Split paths by whitespace or comma while preserving paths enclosed in quotes

$splitPaths = $paths -split "(?<=\S)\s+|(?<=\S),"

foreach ($path in $splitPaths) {

    # Check if the path is enclosed in single or double quotes

    if (-not (($path -like "'*'") -or ($path -like '"*"'))) {

        Write-Host "Error: Path '$path' is not enclosed in single or double quotes."
        exit 1
    }

    # Remove leading and trailing quotes

    $cleanPath = $path.Trim("'").Trim('"')  

    Write-Host "Cleaned Path: $cleanPath"

}

错误输出时不应该有:

Cleaned Path: /u/marsh/UNX/scripts/testscript/test_maillist.txt
Error: Path ''/pathx' is not enclosed in single or double quotes.

恳请建议。

正则表达式 PowerShell 验证 GitHub 用户输入

评论

0赞 lit 11/12/2023
机器上的“有效 UNIX 路径”和“实际路径”之间是否存在细微差别?人们会认为实际的路径是有效的。是否要在 Windows 上运行时验证 UNIX 路径?正则表达式模式是否标识单个字母“驱动器”?提供任何有用的东西吗?Resolve-Path
0赞 Ashar 11/12/2023
@lit我不需要,因为 UNIX 路径的验证必须使用 PowerShell 在 Windows github 运行器上完成。所以只有像 1 这样的语法检查。路径不应为空。2.它应该从原始帖子中提到的其他条件开始,而不是路径的实际存在,这将在我的工作流程中稍后处理。Resolve-Pathactual path/
0赞 An-dir 11/12/2023
是否有必要进行验证?在很多情况下,在使用路径时会进行验证(创建/读取/写入...),您也应该尝试捕获。因此,您可能会进行双重验证。验证是否应遵循特定于文件系统的不允许的路径?正确答案是不同的,这取决于验证后要做什么的细节。要理解我的意思,请阅读 stackoverflow.com/questions/537772/......
0赞 Ashar 11/12/2023
@An-dir 此线程上讨论的大多数解决方案以及类似的解决方案都是关于有效的窗口和 Unix 路径,而此特定帖子适用于用逗号或空格分隔并用单引号或双引号括起来的有效路径。似乎没有检查报价有效性的解决方案,就像我应该为每个打开的报价关闭报价一样
2赞 tripleee 11/12/2023
引号在 Unix 文件名中是完全有效的;唯一无效的字符是 null 字符(当然,目录条目不能包含文本斜杠作为其名称的一部分)。在你的例子中没有韵律或理由,没有额外的人为约束。

答:

2赞 mklement0 11/13/2023 #1

看起来您的输入路径采用字符串文字和/或准字列表的形式:

  • 您的无效路径示例之一 - - 似乎对您的验证施加了不明显的约束:'/tmp/my dir1,/tmp/my dir2'

    • Verbatim 在形式上是一个有效的单一路径,因为它是文件名中的合法字符。/tmp/my dir1,/tmp/my dir2,

      • 从根本上说,正如 tripleee 所指出的,从技术上讲,只有(带码位的字符)在类 Unix 平台上文件系统的路径中是无效的。NUL0x0
    • 因此,下面的解决方案不允许在单个路径中逐字存在 - 根据需要进行调整。,

以下解决方案使用两步方法

  • 它首先通过直接调用 [regex]::Match() API 将路径列表解析为它所表示的逐字项。

    • 有关用于的正则表达式的说明以及试验它的选项,请参阅此 regex101.com 页[regex]::Match()

    • 注意它的局限性:为了(相对)简单,它只支持使用外部引号使用的引号(例如,或)的形式嵌入引号,但不能转义嵌入引号(例如,
      '/foo/3" of snow'"/foo/3'o clock""/foo/3`" of snow"'/foo/3''o clock')

  • 然后,它使用 PowerShell 的 -match 运算符验证每个项目是否表示绝对 Unix 格式路径

    • 有关用于的正则表达式的说明以及试验它的选项,请参阅此 regex101.com 页-match
# Sample input paths.
@(
  # --- valid
  '/tmp/mydir'
  "'/tmp/my  dir1'"
  '"/tmp/my  dir2"'
  "/tmp/mydir '/tmp/my  dir1' '/tmp/my  dir2'"
  "'/tmp/my  dir1','/tmp/my  dir2'"
  # --- invalid
  "'/tmp/my  dir1,/tmp/my  dir2'"
  '/tmp/my  dir1'  # partly valid (1st token)
  "'/tmp/my  dir1"
  "/tmp/my  dir1'"  
) | 
  ForEach-Object {
    # Parse each string as a comma- or whitespace-separated list composed of
    # string literals and/or barewords.
    $match = [regex]::Match(
      $_,
      '^\s*((?:(?<item>[^"''\s,]+)|(?<quote>["''])(?<item>.*?)\<quote>)(?:(?:\s*,?\s*)|$))+$'
    )
    if (-not $match.Success) {
      # Not a well-formed list of string literals and barewords:
      # Report the entire string as invalid.
      [pscustomobject] @{
        Path  = $_
        Valid = $false
      }
    }
    else {
      # List of string literals and barewords, validate each list item.
      $match.Groups['item'].Captures.Value | 
        ForEach-Object {
          [pscustomobject] @{
            Path  = $_
            # To allow "," in paths, remove "," from the regex below.
            Valid = $_ -match '^/(?:[^/\0,]+/?)*$'
          }
        }
      }
    }

输出(请注意,每个输出行代表一个(成功解析的)单个路径):

Path                        Valid
----                        -----
/tmp/mydir                   True
/tmp/my  dir1                True
/tmp/my  dir2                True
/tmp/mydir                   True
/tmp/my  dir1                True
/tmp/my  dir2                True
/tmp/my  dir1                True
/tmp/my  dir2                True
/tmp/my  dir1,/tmp/my  dir2 False
/tmp/my                      True
dir1                        False
'/tmp/my  dir1              False
/tmp/my  dir1'              False

评论

0赞 Ashar 11/13/2023
它有效,但是如果输入路径是变量,您能否建议更改的内容。我是powershell的新手,所以我可能很难调整你的脚本[解决方案]$userinput = "/tmp/mydir '/tmp/my dir1' '/tmp/my dir2'"
0赞 mklement0 11/13/2023
@Ashar:您的示例也适用于上述解决方案:它将字符串值解析为 、 和 ,所有这些都是有效的绝对 Unix 格式路径。这不是你要找的吗?/tmp/mydir/tmp/my dir1/tmp/my dir2
0赞 Ashar 11/13/2023
这正是我正在寻找的,但是您可以建议如果将路径分配给这样的变量,那么您将如何在脚本中处理它# Sample input paths. @( .... )$userinput = "/tmp/mydir '/tmp/my dir1' '/tmp/my dir2'"
0赞 mklement0 11/13/2023
@Ashar:代替上面的整个数组子表达式,提供 (or ) 作为调用的输入,您将看到它按预期处理。@(...)"/tmp/mydir '/tmp/my dir1' '/tmp/my dir2'"$userInputForEach-Object
1赞 Ashar 11/13/2023
工程!!谢谢