用字母替换数字 - powershell

Replace numbers with letters - powershell

我有一个数组元素,我正在尝试用字母替换所有数字。这是操作前的数组元素:

$a[0].object

--- OUTPUT ---
518773112

我将数字转换为字符串并存储在$e中。然后我找到该字符串的长度并将其存储在 $d

$e = $a[0].object.ToString()
$d = $a[0].object.ToString().length
$e
$d

---OUTPUT---
518773112
9

然后我尝试遍历字符串以用字母替换数字。我将 $i 放在子字符串中以获取我要替换的数字。然后我使用 if-statement 查看该子字符串是否等于数字,如果是,然后我使用替换方法尝试用字母替换数字。

for($i=0; $i -lt $d; $i++){
    $pos = $e.Substring($i,1)
    if($pos -eq '0'){$e += $pos.replace('0', 'A')}
    if($pos -eq '1'){$e += $pos.replace('1', 'B')}
    if($pos -eq '2'){$e += $pos.replace('2', 'C')}
    if($pos -eq '3'){$e += $pos.replace('3', 'D')}
    if($pos -eq '4'){$e += $pos.replace('4', 'E')}
    if($pos -eq '5'){$e += $pos.replace('5', 'F')}
    if($pos -eq '6'){$e += $pos.replace('6', 'G')}
    if($pos -eq '7'){$e += $pos.replace('7', 'H')}
    if($pos -eq '8'){$e += $pos.replace('8', 'I')}
    if($pos -eq '9'){$e += $pos.replace('9', 'J')}
}

我的问题是,它会将字母连接到数字字符串的末尾:

518773112FBIHHDBBC

可能,因为我 if-statementthen 部分有 +=。但是,当我将 += 替换为 = 时,我的 Substring 方法出现错误:

Exception calling "Substring" with "2" argument(s): "startIndex cannot be larger than length of string.

我检查了 $i$d,它们在我 运行 循环之前设置正确。所以,我有点困惑。我错过了什么?

String.Replace()方法将为您替换任何匹配字符或子字符串,您无需处理(甚至不关心)字符串中的每个位置分别:

$e = '518773112'

foreach($digit in 0..9){
  # calculate next letter character
  $substitute = ($digit + 'A'[0]) -as [char]

  # replace all instances of $digit with $substitute
  $e = $e.Replace("$digit", $substitute)
}

$e 的值现在是“FBIHHDBBC”

注意,此示例假定值仅为整数。

这是一种方法,首先生成一个从 AJ 的字符集,然后拆分 .object 属性 的值以生成一个这些数字的数组,然后我们可以在字符集上用于 indexing

$char = [char[]]([char]'A'..[char]'J')
$a = [pscustomobject]@{
    object = 518773112
}
$transform = $a.object.ToString() -split '' -ne ''
$a.object = [string]::new($char[$transform])

结果应该是:

PS /> $a

object
------
FBIHHDBBC

$e 会显示为 concatenated ,这是因为你通过循环连接了 $e

函数 subString return 复制 $e 的副本。

你应该声明一个新的变量,

$a[0] = 518773112;
$e = $a[0].ToString()
$d = $a[0].ToString().length

$str = ""
for($i=0; $i -lt $d; $i++){
    $pos = $e.Substring($i,1)
    if($pos -eq '0'){$str += $pos.replace('0', 'A')}
    if($pos -eq '1'){$str += $pos.replace('1', 'B')}
    if($pos -eq '2'){$str += $pos.replace('2', 'C')}
    if($pos -eq '3'){$str += $pos.replace('3', 'D')}
    if($pos -eq '4'){$str += $pos.replace('4', 'E')}
    if($pos -eq '5'){$str += $pos.replace('5', 'F')}
    if($pos -eq '6'){$str += $pos.replace('6', 'G')}
    if($pos -eq '7'){$str += $pos.replace('7', 'H')}
    if($pos -eq '8'){$str += $pos.replace('8', 'I')}
    if($pos -eq '9'){$str += $pos.replace('9', 'J')}
}

Write-Output $str;

尽管有更好的方法来完成同样的工作

要通过单个 regex-based
-replace 操作为现有的有用答案添加简洁的替代方法:

# PowerShell (Core) 7+ only.
# -> 'FBIHHDBBC'
'518773112' -replace '\d', {  [char] ([int] [char] 'A' + [int] $_.Value) }

# Windows PowerShell alternative:
# (requires direct use of underlying .NET APIs)
[regex]::Replace('518773112', '\d', { param($m) [char] ([int] [char] 'A' + [int] $m.Value) })
  • 正则表达式转义序列 \d 匹配任何单个十进制数字。

  • [int] [char] 'A' + [int] $_.Value 将捕获的数字 ($_.Value) 的值作为整数添加到字符 A 的整数表示中,即它向A.

    Unicode 代码点
  • 结果代码点然后是 re-converted 到一个字符 ([char]),这会产生感兴趣的字母。


至于你试过的

抛开你的方法效率低下,问题是你试图在与 input[=55= 相同的变量中构建你的 result 字符串] 字符串:

  • += 因此 将所需结果附加到输入字符串
  • 只是 = 本质上 将输入字符串替换为正在处理的单个字符,导致后续 .Substring() 调用失败,因为字符串现在是减少到单个字符。

立即 修复将在 新变量 中构建结果(但请注意答案中提供的所有解决方案这里最好):

$e = '518773112'
$d = $e.Length

$result = '' # initialize result string
for($i=0; $i -lt $d; $i++){
  $pos = $e.Substring($i,1)
  # Use += on *$result*
  if($pos -eq '0'){$result += $pos.replace('0', 'A')}
  if($pos -eq '1'){$result += $pos.replace('1', 'B')}
  if($pos -eq '2'){$result += $pos.replace('2', 'C')}
  if($pos -eq '3'){$result += $pos.replace('3', 'D')}
  if($pos -eq '4'){$result += $pos.replace('4', 'E')}
  if($pos -eq '5'){$result += $pos.replace('5', 'F')}
  if($pos -eq '6'){$result += $pos.replace('6', 'G')}
  if($pos -eq '7'){$result += $pos.replace('7', 'H')}
  if($pos -eq '8'){$result += $pos.replace('8', 'I')}
  if($pos -eq '9'){$result += $pos.replace('9', 'J')}
}

$result # Output the result: -> 'FBIHHDBBC'

这是我的两分钱:

-join ('518773112' -split '(.)' -ne '' | Foreach-Object { [char]([int]$_ + 65)})

结果:

FBIHHDBBC

替代 Select-Object

-join ('518773112' -split '(.)' -ne '' | Select-Object @{Name = 'Chr'; Expression = {[char]([int]$_ + 65)}}).Chr

另一个简洁的(灵感来自):

-join '518773112'.ToCharArray().ForEach{[char]([int]$_ + 17)}

这个converts the input string into a char array, then loops over each character using PowerShell's intrinsic method ForEach.

ForEach的脚本块中,字符的代码点递增到数字范围'0'..'9',然后转换回字符. “魔术”数字 17 只是字符 'A''0' 的代码点之间的差异(即 [int][char]'A' - [int][char]'0' 输出 17)。

最后,-join 运算符的一元形式用于从各个字符创建单个字符串。