为什么PowerShell变量内容不能进行比较?

日期: 2012-08-20 作者:Don Jones翻译:唐琼瑶 来源:TechTarget中国 英文

下面是一个简短的代码片段,演示了最常见的一个PowerShell问题:   $file = Dir C:MyDirectory   if ($file.name –like ‘*archive*’) {    Write-Host “$($file.name) is an archive”   }   这段代码的目的是查看大量的文件,并确定文件名是否含有单词“archive”。不幸的是,这个脚本里有一些经典的错误。   首先, PowerShell中的Dir命令有可能返回多个对象以及多种类型的对象。当在文件系统驱动器运行时,返回文件和文……

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

下面是一个简短的代码片段,演示了最常见的一个PowerShell问题:

  $file = Dir C:MyDirectory

  if ($file.name –like '*archive*') { 

  Write-Host "$($file.name) is an archive"

  }

  这段代码的目的是查看大量的文件,并确定文件名是否含有单词“archive”。不幸的是,这个脚本里有一些经典的错误。

  首先, PowerShell中的Dir命令有可能返回多个对象以及多种类型的对象。当在文件系统驱动器运行时,返回文件和文件夹。在这种情况下,该脚本将是一个不错的命令,因为两个文件和文件夹有一个Name属性($file.name引用名称属性),但是这可能并不是你所希望得到的。在PowerShell v3中,你可以通过添加-File参数限制Dir命令只返回文件。阅读帮助命令查看其他你可以指定的限制。

  第二, 脚本中的$file变量通常包含多个对象,因为文件系统中大部分文件夹包含其他文件夹和多个文件。但这并不总是一个问题,因为PowerShell能很好地把多个对象放到一个变量中。

  下面的比较存在问题:

  if ($file.name –like '*archive*') {

  你打算用哪个文件的Name属性同“*archive *”比较?在PowerShell v3中,使用 $file.name是完全合法的。深入了解,PowerShell将此命令描述成“我想访问$file变量中所有对象的Name属性。”结果仍是多个对象。在这种情况下,结果包含了多个文件和文件夹的名称的字符串对象。

  问题在于PowerShell的比较运算符,如–like运算符,不能处理多个对象。这些运算符设计用于返回True与False值。如果某些文件命名包含archive而其他没有,返回Maybe值时,运算符该如何做呢?

  解决这个问题的方法是列举文件,因此一次就比较一个。

  对于PowerShell v3,正确方式是:

  $files = Dir C:MyDirectory –File

  foreach ($file in $files) { 

  if ($file.name –like '*archive*') {  
 
  Write-Host "$($file.name) is an archive" 

  }

  }

  Foreach架构目的是接收第二文件($files)中的多个对象,然后每次移动集合中的一个对象。每一次经过,架构从集合中采收一个对象,将其放置在变量的首个专门文件中(例如$file)。以这种方式,你可以每次只运行一个对象。

  虽然使用同个单词的单数与复数很常见,比如$file与$files,但不需要使用Foreach。这样做可让你的代码更易读,但PowerShell不关心这点。

  下面代码也有效:

  $apples = Dir C:MyDirectory –File

  foreach ($fred in $apples) {

    if ($fred.name –like '*archive*') {

      Write-Host "$($fred.name) is an archive"

    }

  }

  在PowerShell中,有多种方式做任何事。下面的代码也能实现上面的结果:

  Dir C:MyDirectory –File |

  foreach-object {

  if ($_.name –like '*archive*') {

  Write-Host "$($_.name) is an archive" 

  }

  }

  该种技术使用ForEach-Object cmdlet代替Foreach脚本架构。这个cmdlet使用不同的语法,不用给其具体的变量名称。相反,它给你一个预定的变量($),每次只包含一个对象。两种技术花费的时间都相同,实现的效果都一样。

  你也可以这样做:

  Dir C:MyDirectory –File |

  where-object { $_.name –like '*archive*' } |

  foreach-object { 

  Write-Host "$($_.name) is an archive"

  }

  这使用了命令行技术而不是脚本类型的技术,但也完全有效。

  学习PowerShell最困难的地方在于任何任务都有太多有效方式可选。如果你要成功地将其他例子改头换面,貌似你需要懂得所有的实现方式。这种多样性也意味着你能采用你熟悉的方式,平衡你给环境带来的现有技巧。

  了解我的人可能疑惑为啥我这么唠叨,在本文中碎碎念Write-Host的使用案例。这绝对不是从脚本生产输出的最佳方式,当然在以后文章中我会详解的哦。

作者

Don Jones
Don Jones

投稿作者

相关推荐