PowerShell - Преобразование имен свойств из регистра Pascal в верхний регистр с подчеркиванием - PullRequest
0 голосов
/ 17 декабря 2018

Допустим, у меня есть такой объект:

$test = @{
          ThisIsTheFirstColumn = "ValueInFirstColumn"; 
          ThisIsTheSecondColumn = "ValueInSecondColumn"
         }     

, и я хочу получить:

$test = @{
          THIS_IS_THE_FIRST_COLUMN = "ValueInFirstColumn"; 
          THIS_IS_THE_SECOND_COLUMN = "ValueInSecondColumn"
         } 

без ручного кодирования имен новых столбцов.

Это показывает мне значения, которые я хочу:

$test.PsObject.Properties | where-object { $_.Name -eq "Keys" } | select -expand value | foreach{ ($_.substring(0,1).toupper() + $_.substring(1) -creplace '[^\p{Ll}\s]', '_$&').Trim("_").ToUpper()} | Out-Host

, что приводит к:

THIS_IS_THE_FIRST_COLUMN
THIS_IS_THE_SECOND_COLUMN

, но теперь я не могу понять, как присвоить эти новые значения обратнопредмет.

Ответы [ 3 ]

0 голосов
/ 18 декабря 2018

Вы можете изменить хеш-таблицу $test на месте следующим образом:

foreach($key in @($test.Keys)) { # !! @(...) is required - see below.
  $value = $test[$key] # save value
  $test.Remove($key)   # remove old entry
  # Recreate the entry with the transformed name.
  $test[($key -creplace '(?<!^)\p{Lu}', '_$&').ToUpper()] = $value
}

@($test.Keys) создает массив из существующих ключей хеш-таблицы;@(...) гарантирует, что коллекция ключей будет скопирована в статический массив , поскольку использование свойства .Keys непосредственно в цикле, который изменяет ту же самую хеш-таблицу, прервется.

Тело цикла сохраняетзначение для ключа ввода под рукой, а затем удаляет запись под старым именем. [1]

Запись затем воссоздается под новым именем ключа с использованием требуемого преобразования имени:

$key -creplace '(?<!^)\p{Lu} соответствует каждой заглавной букве (\p{Lu}) в данном ключе, кроме начала строки ((?<!^)), и заменяет ее на _, за которым следует эта буква (_$&);преобразование результата в верхний регистр (.ToUpper()) дает желаемое имя.


[1] Удаление старой записи перед добавление переименованной позволяет избежать проблем с однословные имена, такие как Simplest, чье преобразованное имя SIMPLEST считается таким же именем из-за нечувствительности к регистру hasthables в PowerShell.Таким образом, присвоение значения записи SIMPLEST, пока запись Simplest все еще существует, фактически нацеливается на существующую запись , и последующая $test.Remove($key) просто удалит эту запись, не добавив новую.
Наконечник шляпы JosefZ за указание на проблему.

0 голосов
/ 18 декабря 2018

Интересно, можно ли сделать это на месте на исходном объекте?

($test.PsObject.Properties|Where-Object {$_.Name -eq "Keys"}).IsSettable говорит False.Следовательно, вам нужно сделать это в два этапа следующим образом:

$test = @{
          ThisIsTheFirstColumn = "ValueInFirstColumn"; 
          ThisIsTheSecondColumn = "ValueInSecondColumn"
         }
$auxarr = $test.PsObject.Properties |
  Where-Object { $_.Name -eq "Keys" } | 
    select -ExpandProperty value 
$auxarr | ForEach-Object { 
    $aux = ($_.substring(0,1).toupper() + 
    $_.substring(1) -creplace '[^\p{Ll}\s]', '_$&').Trim("_").ToUpper()
    $test.ADD( $aux, $test.$_)
    $test.Remove( $_)
}
$test

Двухэтапный подход необходим, поскольку попытка выполнения методов REMOVE и ADD в единственном конвейере приводит к следующей ошибке:

select : Collection was modified; enumeration operation may not execute.

Редактировать .К сожалению, вышеприведенное решение не сработало бы в случае использования однословного ключа Pascal Case , например, для Simplest = "ValueInSimplest".Вот улучшенный скрипт:

$test = @{
          ThisIsTheFirstColumn = "ValueInFirstColumn"; 
          ThisIsTheSecondColumn = "ValueInSecondColumn"
          Simplest = "ValueInSimplest" # the simplest (one word) PascalCase
         }
$auxarr = $test.PsObject.Properties |
  Where-Object { $_.Name -eq "Keys" } | 
    select -ExpandProperty value
$auxarr | ForEach-Object { 
    $aux = ($_.substring(0,1).toupper() + 
      $_.substring(1) -creplace '[^\p{Ll}\s]', '_$&').Trim("_").ToUpper()
    $newvalue =  $test.$_
    $test.Remove( $_)
    $test.Add( $aux, $newvalue)
}
$test
0 голосов
/ 18 декабря 2018

Это похоже на работу.Но я все-таки положил материал в новую хеш-таблицу.

$test = @{
          ThisIsTheFirstColumn = "ValueInFirstColumn"; 
          ThisIsTheSecondColumn = "ValueInSecondColumn"
         }  
$test2=@{}
$test.PsObject.Properties | 
    where-object { $_.Name -eq "Keys" } | 
    select -expand value | foreach{ $originalPropertyName=$_
                                    $prop=($_.substring(0,1).toupper() + $_.substring(1) -creplace '[^\p{Ll}\s]', '_$&').Trim("_").ToUpper()
                                    $test2.Add($prop,$test[$originalPropertyName])
                                  } 
$test2
...