regex 我需要powershell脚本来验证用户输入的有效unix路径

mrfwxfqh  于 12个月前  发布在  Shell
关注(0)|答案(1)|浏览(79)

我需要验证用户是否输入了有效的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.


好心的建议。

km0tfn4u

km0tfn4u1#

看起来你的输入路径是以 string literals 和/或 barewords 的 * list * 的形式:

  • 你的一个无效路径示例-'/tmp/my dir1,/tmp/my dir2'-似乎对你的验证施加了一个不明显的约束:
  • 如果,是文件名中的合法字符,则逐字/tmp/my dir1,/tmp/my dir2在形式上是有效的 * 单一 * 路径。
  • 从根本上说,正如tripleee所指出的,从技术上讲,只有NUL(代码点为0x0的字符)在类Unix平台上的文件系统中的路径中是无效的。
  • 因此,下面的解决方案不允许在单个路径中存在逐字,-根据需要进行调整。

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

  • 它首先通过直接调用[regex]::Match() API,将路径的 * 列表 * 解析为它所表示的 * 逐字 * 项。
  • 有关[regex]::Match()使用的正则表达式的解释以及使用它的选项,请参见this regex101.com page
  • 注意它的限制:为了(相对)简单起见,它只支持 * 嵌入式 * 引用,其形式是使用外部引用所使用的引号 * 而不是 *(例如,

'/foo/3" of snow'"/foo/3'o clock"),但也不能使用 * 转义 * 嵌入式引号(例如,"/foo/3" of snow"'/foo/3''o clock'`)

  • 然后,它使用PowerShell的-match运算符验证每个项是否表示 * 绝对Unix路径 *。
  • 有关-match使用的正则表达式的解释以及使用它的选项,请参见this regex101.com page
# 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

相关问题