PowerShell-字符串中的复杂替换



关于文件名中的复杂替换,我有一个非常复杂的问题,我将尝试解释它

我正在阅读一个在我们公司有约定签名的文件名,例如:%20,_代表一个不同的标志。

'%20' represent a space 
'_' represent '/'

根据这些迹象,我正在TFS中的正确位置搜索文件,它运行良好当">"真的代表"/"时,但当">"是名称的一部分时会发生什么?

让我们看一个简单的例子,而文件名mail_sp.sql中只有一个"_"它可以转换为:mail/sp.sql或mail_sp.sql这是我写的代码(我不知道它是否有效,请随时更正我)

CheckFileExistsTfs是一个返回True或False的函数,这取决于文件是否存在于TFS 中

function CheckFileExistsTfs {
param(
[Parameter(Mandatory)]
[string] $tfsFilePath,
[string] $userName,
[string] $userPassword,
[string] $userDomain
)
Add-Type -AssemblyName 'System.Net.Http'
$clientHandler = New-Object System.Net.Http.HttpClientHandler
if ($userName) {
$clientHandler.Credentials = new-object System.Net.NetworkCredential($userName, $userPassword, $userDomain)
}
else {
$clientHandler.UseDefaultCredentials = 1
}

$client = New-Object System.Net.Http.HttpClient($clientHandler)
$tfsBranchPath = "https://tfs.bandit.com/DefaultCollection/Idu Client-Server/_apis/tfvc/items?scopePath=$tfsFilePath"
#Write-Host "Sending get request (items api) to url: " $tfsBranchPath
$response = $client.GetAsync($tfsBranchPath).Result
$contentObjects = $response.Content.ReadAsStringAsync().Result | ConvertFrom-Json
$exists = $contentObjects.count -eq 1

$fileSize = 0

if ($exists) {
$fileSize = $contentObjects.value[0].size / 1024
}   
$result = [PSCustomObject]@{
FileExists      = $exists
FileSizeInBytes = $fileSize
}
return $result
}

$PatchBranch是TFS中的路径,类似于$/Idu Client Server/Branchs/V6.4/Releases/v8.6.24-CU/Database/

$sql = mail_sp.sql
$newname = $sql.Name.Replace('%20', ' ').replace('_', '/')
$filePathInTfs = $PatchBranch + $new
$fileExist = CheckFileExistsTfs $filePathInTfs
if ($fileExist)
{ Write-Host "TFS file existance is: [$fileExist] by path [$filePathInTfs]" }

elseif (!$fileExist) {
$new = $sql.Name.Replace('%20', ' ')
$filePathInTfs = $PatchBranch + $new
$fileExist = CheckFileExistsTfs $filePathInTfs
if ($fileExist) 
{ Write-Host "TFS file existance is: [$fileExist] by path [$filePathInTfs]" }
}
else { Write-Host "TFS file not exist : [$fileExist] by path [$filePathInTfs] " }

但是如果名称是mail_sp_sp.sql呢?甚至更多的"_"将是许多组合:

mail/sp_sp.sql
mail/sp/sql.sql
mail_sp/sql.sql
mail_sp_sql.sql
mail/sp_sql.sql

其他示例:

AD%20mail_sp.sql应转换为:

AD mail_sp.sql
AD mail/sp.sql

目标是检查每个组合,如果其中一个为真,则停止迭代并显示消息,只有当所有尝试都失败时,才会返回false或给出正确的消息。

我所要求的是检查第一个代码是否有效(当只有一个"_"时),并帮助检查复杂的组合感谢

前导

根据评论,为了转述你的问题以确保我理解它,你有一个文件路径,你通过用_替换/,用%20替换(空格)对其进行了编码。您想反转编码以返回原始文件路径,但您的编码不明确:

编码字符串中的_可能表示原始文件路径中的/_
  • 编码字符串中的%20可能表示原始文件路径中的%20(空格)
  • 因此,您需要生成所有可能的原始值,然后找到文件系统中存在的值。

    顺便说一句,这就是为什么很多编码都有";转义序列";因此,您可以知道字符串的某些部分是文字还是令牌——例如,在C#var x = "line1nline2nline3";中,n明确地表示一个换行符。如果您想要字符串文字n,则必须像这样转义var x = "line1\nline2\nline3";。这样,任何编码字符串都只能表示一个原始值。

    如果可以的话,您可能希望通过添加转义符来重新访问编码规则,以使编码字符串明确无误。

    回答

    不久前,我为一个不同的问题写了一个答案,关于将西里尔字母的单词音译为拉丁字符,你可以重新调整用途——参见可变音译(powershell)。

    你所需要做的就是这样更改查找表:

    function ConvertTo-DecodedPath
    {
    param(
    [string] $InputString
    )
    $lookups = [ordered] @{
    # single character substitutions
    # (we need to use the [char] cast to force case sensitivity for keys)
    [char] "_" = @( "_", "/" )
    # multi-character substitutions
    [string] "%20" = @( "%20", " " )
    }
    # if the input is empty then there's no work to do,
    # so just return an empty string
    if( [string]::IsNullOrEmpty($InputString) )
    {
    return [string]::Empty;
    }
    # find all the lookups that can be applied at the start of the string
    $keys = @( $lookups.Keys | where-object { $InputString.StartsWith($_) } );
    # if there are no lookups found at the start of the string we'll keep
    # the first character as-is and prefix it to all the transliterations
    # for the remainder of the string
    if( $keys.Length -eq 0 )
    {
    $results = @();
    $head    = $InputString[0];
    $rest    = $InputString.Substring(1);
    $tails   = ConvertTo-DecodedPath -InputString $rest;
    foreach( $tail in $tails )
    {
    $results += $head + $tail;
    }
    return $results;
    }
    # if we found any lookups at the start of the string we need to "multiply"
    # them with all the transliterations for the remainder of the string
    $results = @();
    foreach( $key in $keys )
    {
    if( $InputString.StartsWith($key) )
    {
    $heads = $lookups[$key];
    $rest  = $InputString.Substring(([string] $key).Length);
    $tails = ConvertTo-DecodedPath -InputString $rest;
    foreach( $head in $heads )
    {
    foreach( $tail in $tails )
    {
    $results += $head + $tail;
    }
    }
    }
    }
    return $results;
    }
    

    示例

    下面是一个基于示例字符串的示例。请注意,这些值与您列出的值不同,但我认为您的列表可能是错误的,因为我看不出mail_sp_sp.sql如何成为以sql.sql:-结尾的任何字符串。

    PS> ConvertTo-DecodedPath "mail_sp_sp.sql"
    mail_sp_sp.sql
    mail_sp/sp.sql
    mail/sp_sp.sql
    mail/sp/sp.sql
    

    问题

    如果存在多个解码路径,接下来会发生什么?

    相关内容

    • 没有找到相关文章

    最新更新