关于文件名中的复杂替换,我有一个非常复杂的问题,我将尝试解释它
我正在阅读一个在我们公司有约定签名的文件名,例如:%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
问题
如果存在多个解码路径,接下来会发生什么?