PowerShell教程 – 编程结构(Program Struct)- 第一部分


更新记录
转载请注明出处。
2022年8月21日 发布。
2022年8月18日 从笔记迁移到博客。

变量(Variables)

变量说明

A variable may be of any .NET type or object instance
PowerShell并没有对变量有太多限制
不需要在使用变量前对其进行显式声明或定义
可以使用中更改变量值的类型
所有东西在PowerShell中都是对象
一个简单的字符串,比如计算机名,都被当作对象对待

定义变量(Naming and creating variables)

变量的语法规则:
Variables in PowerShell are preceded by the dollar symbol ($)
The name of a variable may contain numbers, letters, and underscores

[类型]$变量名

实例:
字符串都是System.String类型

"Panda666.com" | Get-Member

支持的类型:

[int]					整型数字
[single][double]	单精度和多精度浮点型数值(小数位部分的数值)
[string]		     字符串
[char]			     字符(如[char]$c='X')
[xml]			  XML文档(比如[xml]$doc=Get-Content MyXML.xml)
[adsi]			  活动目录服务接口(ADSI)查询
			       Shell会执行查询并把结果对象存入变量
			      (如[adsi]$user="WinNT://MYDOMAIN/Administrator,user")

实例:

$panda = 666
$panda = "Panda666.com"

变量名称可以很长,长到可以不用考虑它到底能有多长
变量名称可以包含空格,但是名字必须被花括号包住
比如${My Variable},表示一个变量名“My Variable”
不建议这么用,容易出错且不易阅读
实例:

${Panda 666} = "Panda666.com"

注意:
变量不会驻留在Shell会话之间
当关闭Shell,所有创建的变量都会被清除

读取变量

$panda

注意:
变量可以放在””双引号中,会被解析
变量可以放在”单引号中,不会被解析
读取不存在的变量不会报错
实例:

$panda = "Panda666.com"
"My Website = $panda"   #My Website = Panda666.com
'My Website = $panda'	   #My Website = $panda

变量类型定义 和 类型转换(Types and type conversion)

Type conversion in PowerShell is used to switch between different types of a value
变量的类型可以是:.NET type, a class, or an enumeration

PowerShell支持以下类型的转换:
Direct assignment
Language-based conversion
Parse conversion
Static create conversion
Constructor conversion
Cast conversion
IConvertible conversion
IDictionary conversion
PSObject property conversion
TypeConverter conversion

实例:
定义字符串变量

[String]$thisString = "some value"

定义数值变量

[Int]$thisNumber = 2

定义日期DateTime变量

[DateTime]$date = '01/01/2016'

将变量赋值为$null将不会改变其类型

[string]$name = "Panda";
$name = $null;
$name.GetType();   //String

字符串类型转为数值类型

[int]"123"

将日期类型转为字符串类型

[String](Get-Date)

字符串类型转为DateTime类型

[DateTime]"01/01/2016"

以下情况会被转为bool值的true

[Boolean]1
[Boolean]-1
[Boolean]2016
[Boolean]"Hello world"

以下情况会被转为bool值的false

[Boolean]0
[Boolean]""
[Boolean]$null

变量相关的命令

创建新变量

New-Variable

实例:
创建变量存放字符串

New-Variable –Name One –Value 'Hello'

创建变量存放数组

New-Variable -Name "Panda" -Value 1,2,3,4 

创建变量存放哈希表

New-Variable -Name "Panda3" -Value @{ ID = 1; Shape = "Square"; Color = "Blue"}

创建变量存放日期

New-Variable -Name today -Value (Get-Date)

定义常量

New-Variable -Name startTime -Value (Get-Date) -Option Constant

设置变量的值

Set-Variable

实例:
设置变量存放数值类型

Set-Variable -Name One -Value 123

设置变量存放数组

Set-Variable -Name "Panda" -Value 1,2,3,4,5,6 

设置变量存放哈希表

Set-Variable -Name "Panda" -Value @{"Name"="Panda"}

设置变量的描述

Set-Variable objectCount -Description 'The number of objects in the queue'

移除变量

删除变量的名和释放变量的值

Remove-Variable

实例:
移除指定变量

Remove-Variable -Name One

清除变量

清除变量的值

Clear-Variable

实例:
移除指定名称的变量

Clear-Variable -Name "Panda2"

获得变量

获得已定义的和预定义的变量

Get-Variable

实例:

获得用户定义的变量

$panda = 666;
Get-Variable panda

获得所有已存在的变量

Get-Variable | Select-Object Name, Description

变量提供器(Variable provider)

PowerShell includes a variable provider that can be queried as a filesystem
使用变量提供器,可以将文件系统使用的命令直接用在变量中

实例:
获得所有已经定义的变量

Get-ChildItem variable:

检测变量存在

Test-Path variable:/VerbosePreference

创建新的变量

Set-Item variable:/new -Value variable

获得变量的内容

Get-Content variable:/OutputEncoding 

解构赋值

分割字符串进行解构赋值

$firstName, $lastName = "First Last" -split " "
$firstName, $lastName = "First Last".Split(" ")

拆分数组进行解构赋值

$i, $j = 1, 2

最后一个变量获得数组最后的全部元素

$i, $j, $k = 1, 2, 3, 4, 5 

最后一个变量没有被赋值

$i, $j, $k = 1, 2

作用域(Variable Scope)

作用域类型(Scope Type)

Variables may be declared in a number of different scopes
The scopes are as follows:
全局作用域(Global Scope)
局部作用域(Local Scope)
脚本作用域(Script Scope)
私有作用域(Private Scope)
A numeric scope relative to the current scope
image

By default, variables are placed in local scope
Access to variables is hierarchical
Child (scopes created beneath a parent) can access variables created by the parent
Variables created in a child scope cannot be accessed from a parent scope
如果变量在本地作用域没有查到,则向上作用域继续查找

实例:
获得作用域的帮助信息

Get-Help about_scopes

本地和全局作用域(Local and Global Scope)

When creating a variable in the console (outside of functions or script blocks), the local scope is global

实例:

定义局部作用域的变量

$Local:thisValue = "Some value"

定义全局作用域的变量

$global:thisValue = 123

访问全局作用域的变量

$Local:pandaOuter = "panda666"
function Test-ThisScope {
 	"From Local: $local:thisValue" 			# Does not exist
 	"From Global: $global:pandaOuter" 	# Accessible
}
Test-ThisScope

全局作用域(Global Scope)

Shell本身具有最高级的作用域,称为全局域(global scope)

脚本作用域(Script Scope)

当运行一个脚本时,会在脚本范围内创建一个新的作用域
脚本作用域是全局作用域的子集,也就是全局作用域的子作用域(child)
全局作用域是脚本作用域的父作用域(parent)

实例:
显式定义脚本作用域内的变量

[Version]$Script:Version = "0.1"

在函数内访问同名全局作用域需要使用全局修饰符
注意:如果非同名,可以直接使用变量名

function Set-Version {
   param(
     [Version]$version
   )
   $Script:Version = $version
}

私有作用域(Private Scope)

函数还有其特有的私有作用域(private scope)
The private scope may be accessed using the private prefix
注意:私有作用域仅在自己的作用域内可用

实例:
定义私有作用域

$private:thisValue = "Some value"

私有作用域仅在自己的作用域内可用

定义私有作用域变量

$private:pandaPrivate = "panda666"
"From global: $global:pandaPrivate"    # Accessible
function Test-ThisScope {
 "Without scope: $pandaPrivate"           # Not accessible
 "From private: $private:pandaPrivate"    # Not accessible
 "From global: $global:pandaPrivate"      # Not accessible
}
Test-ThisScope

如果变量在当前作用域找到了匹配的变量,则不会向上查找

function bottom {
    $thisValue = "Bottom"
    Write-Host "Bottom: $thisValue"
    middle
}
function middle {
    # Hide thisValue from children
    $private:thisValue = "Middle" # Middle only
    Write-Host "Middle: $thisValue"
    top
}
function top {
    Write-Host "Top: $thisValue" # Original value
}
#调用
Bottom

作用域规则(Scope Rule)

如果尝试访问一个作用域元素,PowerShell在当前作用域内查找
如果不存在于当前作用域,PowerShell会查找其父作用域,依此类推
直到找到树形关系的顶端全局作用域

数组(Arrays)

数组类型变量说明

本质就是dotNet中的System.Array类型
Array类型支持的方法基本都支持
默认数组内的元素类是System.Object
Indexing in an array starts from 0

定义数组类型变量

直接简单定义

定义空数组

$myArray = @()

直接定义数组的元素,使用,分隔值即可
元素可以是任意类型(因为默认的元素类型是Object类型)

$A = 1, 2, 3, 4
$pandaArr = "Panda",666,"Dog",888
$myGreetings = "Hello world", "Hello sun", "Hello moon"
$myGreetings = @("Hello world", "Hello sun", "Hello moon")
$myThings = "Hello world", 2, 34.23, (Get-Date)

默认情况下数值的元素类型是System.Object,可以使用getType方法获得数组类型

$A.getType()

通过序列生成

$A = 1..4

还可以跨越多行

$myGreetings = "Hello world",
 "Hello sun",
 "Hello moon"

定义指定类型

声明数组的类型

[int32[]]$intA = 1500,2230,3350,4000

创建指定类型的数组并指定数组长度

$myArray = New-Object Object[] 10 		# 10 objects
$byteArray = New-Object Byte[] 100 		# 100 bytes
$ipAddresses = New-Object IPAddress[] 5 	# 5 IP addresses

当声明了类型后,如果赋值其他类型将会发生转换
如果无法进行转换,将会抛出异常

[Int32[]]$myNumbers = 1, 2, $null, 3.45

多维数组和锯齿数组的定义(Multi-dimensional and jagged arrays)

多维矩阵数组

$arrayOfArrays = @(
 @(1, 2, 3),
 @(4, 5, 6),
 @(7, 8, 9)
)

多维锯齿数组(Jagged arrays)

$arrayOfArrays = @(
 @(1, 2),
 @(4, 5, 6, 7, 8, 9),
 @(10, 11, 12)
)

数组元素操作

读取数组的元素

索引从0开始

$pandaArr[0]  #Panda
$arrayOfArrays[0][1]

倒序开始访问

$myArray[-1]

访问倒数第二个元素

$myArray[-2]

选择一个范围

$myArray[2..4]
$myArray[-1..-5]

选择多个范围

$myArray[0..2 + 6..8 + -1]
$myArray[0..0 + 6..8 + -1]

获得数组中的部分元素组成新数组

$newArray = $oldArray[0..48] + $oldArray[50..99]

修改数组的元素(Changing element values in an array)

修改数组的单个元素

$myArray = 1, 2, 9, 4, 5
$myArray[2] = 3

遍历修改数组的元素

$myArray = 1, 2, 3, 4, 5
for ($i = 0; $i -lt $myArray.Count; $i++) {
 $myArray[$i] = 9
}

添加元素到数组(Adding elements to an array)

直接添加

$myArray = @()
$myArray += "New value"

直接添加

$myArray = $myArray + "New value"

连接多个数组

$firstArray = 1, 2, 3
$secondArray = 4, 5, 6
$mergedArray = $firstArray + $secondArray

注意:以上操作如果是大数组会导致效率问题

移除数组的元素(Removing elements from an array)

直接将元素设置为null

$myArray = 1, 2, 3, 4, 5
$myArray[1] = $null

使用For循环筛选元素

$newArray = for ($i = 0; $i -lt $oldArray.Count; $i++) {
 if ($i -ne 49) {
 $oldArray[$i]
 }
}

获得数组中的部分元素组成新数组

$newArray = $oldArray[0..48] + $oldArray[50..99]

使用Array.Copy方法

$newArray = New-Object Object[] ($oldArray.Count - 1)
# Before the index

#Array.Copy重载1
[Array]::Copy(
 $oldArray, # Source
 $newArray, # Destination
 49 # Number of elements to copy
)
# #Array.Copy重载2
[Array]::Copy(
 $oldArray, # Source
 50, # Copy from index of Source
 $newArray, # Destination
 49, # Copy to index of Destination
 50 # Number of elements to copy
)

通过Where-Object命令移除不需要的元素

$newArray = $oldArray | Where-Object { $_ -ne 50 }

获得数组的长度

$pandaArr.count

查找数组的某个元素

$pandaArr.IndexOf(666)

遍历数组

使用For-Each进行遍历

$myArray | ForEach-Object { Write-Host $_ }

使用for循环进行遍历

$arr = 1..3
for ($i = 0; $i -le ($arr.length - 1); $i += 1) {
  Write-Host $i;
}

清空数组(Clearing an array)

$newArray = 1, 2, 3, 4, 5
$newArray.Clear()

哈希表(Hashtable)

说明

哈希表存储键值对(key/value pairs)
通常使用String或者 numbers作为键
A hashtable is an associative array or an indexed array
Individual elements in the array are created with a unique key
Keys cannot be duplicated within the hashtable

定义哈希表(Declaring hashtable Variables)

定义空哈希表

$hash = @{}

定义包含成员的哈希表

$hash = @{ ID = 1; Shape = "Square"; Color = "Blue"}

定义有序哈希表(Ordered dictionaries)

$hash = [ordered]@{ ID = 1; Shape = "Square"; Color = "Blue"}

将成员放置在多行,方便阅读代码
注意:多行方式,元素之间没有符号分隔

$hashtable = @{
 Key1 = "Value1"
 Key2 = "Value2"
}

哈希表操作

获得哈希表元素(accessed through the keys)

$hash["ID"]

也可以使用属性的形式

$hashtable.Key1

数值键也可以直接使用方法的形式

$hashtable = @{1 = 'one'}
$hashtable.1
$hashtable[1]

修改元素值

$hash["Updated"] = "Now"
### 获得哈希表的所有键
$hash.keys
### 获得哈希表的所有值
$hash.values
### 添加元素到哈希表

注意:添加前记得检测键是否已经存在,否则重复的键会造成抛出异常

$hash.Add("Created","Now")

或者使用方法的形式添加

$pandaHashTable = @{
    "Name"="Panda666"
};
$pandaHashTable.Hobby = 'Computer','Girl','CoCo'

还可以直接使用索引式添加

$pandaHashTable = @{
    "Name"="Panda666"
};
$pandaHashTable['Code'] = 666; 

移除元素(Removing elements from a hashtable)

注意:如果Key不存在,不会报错
注意:不可以在遍历循环中移除元素

$hash.Remove("Code")

可以使用折中的方式进行循环删除元素

$pandaHashTable = @{
    Name = "Panda666"
    Code = 666
    Hobby = "Computer","PowerShell","Windows","Girl"
};

[object[]] $keys = $pandaHashTable.Keys;
foreach($key in $keys)
{
    $pandaHashTable.Remove($key);
}

清除所有元素

$hashtable = @{one = 1; two = 2; three = 3}
$hashtable.Clear()

获得哈希表的枚举器

$hash.GetEnumerator()

检测哈希表是否包含指定元素的键

$pandaHashTable = @{
    "Name"="Panda666"
};
$pandaHashTable.ContainsKey("Name");

检测哈希表是否包含指定元素的值

$pandaHashTable = @{
  "Name"="Panda666"
};
$pandaHashTable.ContainsValue("Panda666");

遍历循环获得哈希表的元素

注意:这种方式的遍历不可以修改哈希表

$pandaHashTable = @{
    "Name" = "Panda"
    "Code" = 666
};

foreach($key in $pandaHashTable.Keys)
{
    Write-Host $pandaHashTable[$key];
}

可以使用折中的方式进行修改哈希表

$hashtable = @{
   Key1 = 'Value1'
   Key2 = 'Value2'
}
[Object[]]$keys = $hashtable.Keys
foreach ($key in $keys) {
   $hashtable[$key] = "NewValue"
}

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/281415.html

(0)
上一篇 2022年8月21日
下一篇 2022年8月21日

相关推荐

发表回复

登录后才能评论