更新参考 table 的字符串值 - Powershell

Updating a string value with reference to a table - Powershell

我有一个脚本来更新校准文件中的字符串值,但我真的坚持基于以下查找进行更新 table:

Level   PARALLEL_VOLTAGE_TEST   PARALLEL_VOLTAGE_REF
1   85  250
2   90  250
3   95  250
4   100 250
5   105 250
6   110 250
7   115 250
8   120 250
9   125 250
10  130 250
11  135 250
12  140 250
13  145 250
14  150 250
15  155 250
16  160 250
17  165 250
18  170 250
19  175 250
20  180 250
21  185 250
22  190 250
23  195 250
24  200 250
25  205 250
26  205 245
27  205 240
28  205 235
29  205 230
30  205 225
31  205 220
32  205 215
33  205 210
34  205 205
35  205 200
36  205 195
37  205 190
38  205 185
39  205 180
40  205 175
41  205 170
42  205 165
43  205 160
44  205 155
45  205 150
46  205 145
47  205 140
48  205 135
49  205 130
50  205 125

例如,如果输入文件有一行的 PARALLEL_VOLTAGE_TEST 值为 85,PARALLEL_VOLTAGE_TEST 值为 185,我需要在 table 并将这些值替换为下面 20 个级别(table 行)的值。如果没有这样的行,则应使用 last table 行中的值。

这是带有硬编码值对的示例代码,(85, 250)(级别1),应替换为级别21(185, 250),但我需要推广这种方法以处理所有值对:

$file = 'C:\Users\sugas\Desktop\Test\*.cal'
$VTEST = (Get-Content $file | select-string "PARALLEL_VOLTAGE_Test")
$VREF = (Get-Content $file | select-string "PARALLEL_VOLTAGE_REF")

if (($VTEST-imatch 'PARALLEL_VOLTAGE_Test 85') -and ($VREF-imatch 'PARALLEL_VOLTAGE_REF 250')) {
(Get-Content $file).replace($VTEST,'PARALLEL_VOLTAGE_Test 185')| Set-Content $file
(Get-Content $file).replace($VREF,'PARALLEL_VOLTAGE_REF 250') | Set-Content $file
}

您可以采用以下方法:

  • 读取 table 值并将其转换为散列table,将测试电压、参考电压对映射到它们的移位 20 项值,或者,如果不存在这样的条目,则到最后一个 table 条目。

  • 在输入文件中查找包含两个 测试电压和参考电压条目的行:

    • 从这些线路中提取电压值,
    • 在散列中查找它们table、
    • 并将这些值替换为移位后的值。

以下解决方案演示了这种方法:

# Read the table into objects.
# The -replace operation compresses runs of multiple spaces into one space
# each, so that ConvertFrom-Csv -Delimeter ' ' can be used to read the 
# input as a CSV file.
$table =
  (Get-Content -Raw table.txt) -replace '  +', ' ' | ConvertFrom-Csv -Delimiter ' '

# Create a hashtable that maps (test voltage, ref voltage) pairs to their
# new values, 20 items lower in the table, defaulting to the last table entry
# if there is no such item.
$maxNdx = $table.Count - 1
$voltageMap = [ordered] @{}
foreach ($i in 0..$maxNdx) {
  # Determine the index of the table entry with the shifted values.
  $targetIndex = [math]::Min(20 + $i, $maxNdx)
  # Note: We use a *string* key that is the space-separated concatenation 
  #       of the test and ref values (e.g., '85 100'), 
  $voltageMap["$($table[$i].PARALLEL_VOLTAGE_TEST, $table[$i].PARALLEL_VOLTAGE_REF)"] = $table[$targetIndex].PARALLEL_VOLTAGE_TEST, $table[$targetIndex].PARALLEL_VOLTAGE_REF
}

$reTest = '\b(?<label>PARALLEL_VOLTAGE_TEST +)(?<test>\d+)\b'
$reRef  = '\b(?<label>PARALLEL_VOLTAGE_REF +)(?<ref>\d+)\b'

# Loop over all *.cal files
Get-Item *.cal | ForEach-Object {
  # Process each file line by line.
  $modifiedLines = 
    switch -File $_.FullName -Regex {
      # A line that contains both PARALLEL_VOLTAGE_TEST and PARALLEL_VOLTAGE_REF values, in either sequence.
      "$reTest.*$reRef|$reRef.*$reTest" {
        # Using the capture-group values, look up the shifted voltage values.
        $newTest, $newRef = $voltageMap["$($Matches.test, $Matches.ref)"]
        if ($newTest) { # Match in table found, replace voltage values in the line at hand.
          $_ -replace $reTest, "`${label}$newTest" -replace $reRef, "`${label}$newRef"
        } else { # no match in table found, pass line through
          $_ 
        }
      }
      default { $_ } # Pass all other lines through.
    }
  # Echo the modified lines.
  $modifiedLines
  # NOTE: In order to write the modified lines back to the input file,
  #       uncomment the next line.
  # $modifiedLines | Set-Content $_.FullName
}

注意:如果 PARALLEL_VOLTAGE_TESTPARALLEL_VOLTAGE_REF 值不一定在同一行并且每个文件只有一个 单个 值对:

  • ForEach-Object 脚本块中使用 $content = Get-Content -Raw $_.FullName 将整个文件读入单个字符串

  • 在组合正则表达式前加上 (?s) 前缀,使 . 也匹配换行符。

  • 使用 if ($content -match ...) 而不是 switch 语句。