Powershell String Splitting差异

时间:2013-09-20 21:52:24

标签: string powershell split powershell-v2.0

我试图通过调用$ varname.split(',')在PowerShell中拆分字符串。我在PowerShell控制台中时工作正常,但在我直接调用脚本时却没有。

从命令提示符:powershell .\scriptname.ps1

Method invocation failed because [System.Object[]] doesn't contain a method named 'split'.
At C:\scriptname.ps1:92 char:30
+         reboot $varname.split <<<< (',')
    + CategoryInfo          : InvalidOperation: (split:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

同样,当我在ISE中运行它或直接从PS提示符运行时,这非常正常。想法?

修改:我在下面提供了我的脚本。我是PowerShell的新手,所以我没有看到任何会导致变量仅在通过命令行调用时才能表现为数组。

[string]$servers
[string]$filepath
[string]$account  = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
[string]$mode
[bool]  $reboot   = $FALSE

Write-Host "========================================"
Write-Host "| Windows Server Shutdown Utility v1.0 |"
Write-Host "========================================"

Function usage(){
    Write-Host "Arguments are accepted in any order as long as the data follows the mode."
    Write-Host "<required> [optional]"
    Write-Host "Usage: powershell .\wss.ps1 <-l|-f> <data> [-account] [-reboot] [--help]"
    Write-Host "`tModes"
    Write-Host "`t`t-list: A list of servers, seperated by commas with no spaces inbetween"
    Write-Host "`t`t`tAliases: -l"
    Write-Host "`t`t`t[*] Example: `"ServerA.domain,ServerB.domain`""
    Write-Host "`t`t-file: A path to a file that contains one server name on each line"
    Write-Host "`t`t`tAliases: -f"
    Write-Host "`t`t`t[*] Example: `"C:\allDomainServers.txt`""
    Write-Host "`taccount: The domain and account to use. You will be prompted for a password."
    Write-Host "`t`t`tAliases: -a, -ac"
    Write-Host "`treboot: If specified, the servers will be shutdown instead of rebooted."
    Write-Host "`t`t`tAliases: -r"
    Write-Host "`thelp: Prints the help screen."
    Write-Host "`t`t`tAliases: -h, -help, /help, /?"
    Write-Host "`t`tNOTE: If no account is specified, the current user will be used."

}

Function shutdown($arr){
    $arr | ForEach{
        Write-Host "Attempting to shutdown $_"
        Stop-Computer -computername ($_) -credential ($c) -force
    }
    Write-Host "Finished. Please be aware that some servers may still be in the process of shutting down."
}

Function reboot($arr){
    $arr | ForEach{
        Write-Host "Attempting to reboot $_"
        Restart-Computer -computername ($_) -credential ($c) -force
    }
    Write-Host "Finished. Please be aware that some servers may still be in the process of rebooting."
}

#Parse Arguments
if($args.length -eq 0 -or $args[0] -eq "-help" -or $args[0] -eq "/help" -or $args[0] -eq "--help" -or $args[0] -eq "/?"){
   usage
   exit
}

for($i=0; $i -lt $args.length; $i++){
    $k = $args[$i]
    if($k -eq "-r" -or $k -eq "-reboot"){
        $reboot = $TRUE
    }elseif($k -eq "-a" -or $k -eq "-ac" -or $k -eq "-account"){
        $account = $args[++$i]
    }elseif((!$mode) -and ($k -eq "-l" -or $k -eq "-list")){
        $servers = $args[++$i]
        $mode    = "list"
    }elseif((!$mode) -and ($k -eq "-f" -or $k -eq "-file")){
        $filepath = $args[++$i]
        $mode     = "file"
    }
}

#Verify Account Credentials
$c = get-credential $account

if(!$c){
    Write-Host "No credentials specified!"
    exit
}

if($mode -eq "list"){
    Write-Host "Using Mode: List"
    if([string]::IsNullOrEmpty($servers)){
        usage
        exit
    }

    if($reboot){
        reboot $servers.split(',')
    }else{
        shutdown $servers.split(',')
    }

}elseif($mode -eq "file"){
    Write-Host "Using Mode: File"
    if([string]::IsNullOrEmpty($filepath)){
        $filepath = Read-Host 'Enter the path to the file containing a list of hosts:'
    } 

    if(!(Test-Path $filepath)){
        Write-Host "Error! File doesn't exist!"
        exit
    }

    if($reboot){
        reboot (get-content $filepath)
    }else{
        shutdown (get-content $filepath)
    }

}else{
    Write-Host "Unknown Mode! Got: $mode"
    exit
}

编辑2:请参阅使用此脚本进一步测试:

for($i=0; $i -lt $args.length; $i++){
    Write-Host $args[$i]
    Write-Host $args[$i].GetType()
}

Powershell提示:

PS C:\> .\test.ps1 asdf fdsa
asdf
System.String
fdsa
System.String

PS C:\> .\test.ps1 "asdf,fdas"
asdf,fdas
System.String

PS C:\> .\test.ps1 "asdf","fdas"
asdf fdas
System.Object[]

PS C:\> .\test.ps1 asdf,fdas
asdf fdas
System.Object[]

命令提示符:

C:\>powershell .\test.ps1 asdf fdsa
asdf
System.String
fdsa
System.String

C:\>powershell .\test.ps1 "asdf,fdas"
asdf fdas
System.Object[]

C:\>powershell .\test.ps1 "asdf","asdfa"
asdf asdfa
System.Object[]

C:\>powershell .\test.ps1 asdf,fdas
asdf fdas
System.Object[]

注意它如何处理引用的字符串(测试#2)。为什么会这样?有什么方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

无论出于何种原因,$ varname在脚本中运行时都包含一个数组。并且阵列上没有Split方法。是否可以显示用于确定分配给$ varname的值的脚本?顺便说一句,如果数组包含您要拆分的字符串,请尝试此$varname[0].Split(',')

答案 1 :(得分:1)

我能够通过验证指定的参数是一个字符串来解决我的问题。如果它已经是一个数组,那么它只是传递给函数。这样检查:

if($servers -is [system.string]){
        $servers = $servers.split(',')
}