设为首页收藏本站

 找回密码
 注册

QQ登录

只需一步,快速开始

BCM 门户 IT世界 资料备录 查看内容

Text and Regular Expressions in PowerShell

2011-11-22 10:10| 发布者: Test| 查看: 1347| 评论: 0|来自: powershell.com

摘要: PowerShell distinguishes sharply between text in single quotation marks and text in double quotation marks. PowerShell won't modify text wrapped in single quotation marks but it does inspect text in s ...

PowerShell distinguishes sharply between text in single quotation marks and text in double quotation marks. PowerShell won't modify text wrapped in single quotation marks but it does inspect text in single quotation marks and may modify it by inserting variable contents automatically. Enclosing text in double quotation marks is the foremost and easiest way to couple results and descriptions.

The formatting operator -f, one of many specialized string operators, offers more options. For example, you can use -f to output text column-by-column and to set it flush. Other string commands are also important. They can replace selected text, change case, and much more.

Pattern recognition adds a layer of complexity because it uses wildcard characters to match patterns. In simple cases, you can use the same wildcards that you use in the file system. Substantially more powerful, but also more complex, are regular expressions.

Topics Covered:

Defining Text

Use quotation marks to delimit it if you'd like to save text in a variable or to output it. Use single quotation marks if you want text to be stored in a variable in (literally) exactly the same way you specified it:

$text = 'This text may also contain $env:windir `: $(2+2)'
This text may also contain $env:windir `: $(2+2)

Text will have an entirely different character when you wrap it in (conventional) double quotation marks because enclosed special characters will be evaluated:

$text = "This text may also contain $env:windir `: $(2+2)"
This text may also contain C:\Windows: 4

Special Characters in Text

If text is enclosed in double quotation marks, PowerShell will look for particular special characters in it. Two special characters are important in this regard: "$" and the special backtick character, "`".

Resolving Variables

If PowerShell encounters one of the variables from Chapter 3, it will assign the variable its value:

$windir = "The Windows directory is here: $env:windir"
$windir
The Windows directory is here: C:\Windows

This also applies to direct variables, which calculate their value themselves:

$result = "One CD has the capacity of $(720MB / 1.44MB) diskettes."
$result
One CD has the capacity of 500 diskettes.

Inserting Special Characters

The peculiar backtick character, "`", has two tasks: if you type it before characters that are particularly important for PowerShell, such as "$" or quotation marks, PowerShell will interpret the characters following the backtick as normal text characters. You could output quotation marks in text like this:

"This text includes `" quotation marks`""
This text includes "quotation marks"

If one of the letters listed in Table 13.1 follows the backtick character, PowerShell will insert special characters:

$text = "This text consists of`ntwo lines."
This text consists of
two lines!
Escape Sequence Special Characters
`n New line
`r Carriage return
`t Tabulator
`a Alarm
`b Backspace
`' Single quotation mark
`" Double quotation mark
`0 Null
`` Backtick character

Table 13.1: Special characters and "escape" sequences for text

"Here-Strings": Acquiring Text of Several Lines

Using "here-strings" is the best way to acquire long text consisting of several lines or many special characters. "Here-strings" are called by this name because they enable you to acquire text exactly the way you want to store it in a text variable, much like a text editor. Here-strings are preceded by the @" character and terminated by the "@ character. Note here once again that PowerShell will automatically resolve (assign variable values and evaluate backtick characters in) text enclosed by @" and "@ characters. If you use single quotation marks instead, the text will remain exactly the way you typed it:

$text = @"
Here-Strings can easily stretch over several lines and may also include
"quotation marks". Nevertheless, here, too, variables are replaced with
their values: C:\Windows, and subexpressions like 4 are likewise replaced
with their result. The text will be concluded only if you terminate the
here-string with the termination symbol "@.
"@

$text
Here-Strings can easily stretch over several lines and may also include
"quotation marks". Nevertheless, here, too, variables are replaced with
their values: C:\Windows, and subexpressions like 4 are likewise replaced
with their result. The text will be concluded only if you terminate the
here-string with the termination symbol "@.

Communicating with the User

If you'd like to request users to input text, use Read-Host:

$text = Read-Host "Your entry"
Your entry: Hello world!
$text
Hello world!

Text acquired by Read-Host behaves like text enclosed in single quotation marks. Consequently, special characters and variables are not resolved. Manually use the ExpandString() method if you want to resolve the contents of a text variable later on, that is, have the variables and special characters in it replaced. PowerShell normally uses this method internally when you allocate text in double quotation marks:

# Query and output text entry by user:
$text = Read-Host "Your entry"
Your entry: $env:windir
$text
$env:windir

# Treat entered text as if it were in double quotation marks:
$ExecutionContext.InvokeCommand.ExpandString($text)
$text
C:\Windows

If you'd like to use Read-Host to acquire sensitive data, passwords, use the -asSecureString parameter. The screen entries will be masked by asterisks. The result will be a so-called SecureString. To be able to work on the encrypted SecureString as a normal text entry, it must be changed to plain text first:

$pwd = Read-Host -asSecureString "Password"
Password: *************
$pwd
System.Security.SecureString
[Runtime.InteropServices.Marshal]::`
PtrToStringAuto([Runtime.InteropServices.Marshal]::`
SecureStringToBSTR($pwd))
strictly confidential

Querying User Name and Password

If you'd like to authenticate a user, such as query his name and password, use Get-Credential. This cmdlet uses the secure dialog boxes that are integrated into Windows to request user name and password:

Get-Credential -Credential "Your name?"
UserName Password
-------- --------
\Your name System.Security.SecureString

The result is an object having two properties: the given user name is in UserName and the encrypted password is in Password as an instance of SecureString:

Figure 13.1: Querying user passwords using the integrated secure dialog box

Normally, Get-Credential is used if logon data are actually needed, such as to run a program under a particular user name:

$logon = Get-Credential
$startinfo = new-object System.Diagnostics.ProcessStartInfo
$startinfo.UserName = $logon.UserName
$startinfo.Password = $logon.Password
$startinfo.FileName = "$env:windir\regedit.exe"
$startinfo.UseShellExecute = $false
[System.Diagnostics.Process]::Start($startinfo)

However, the user context that creates the Secure String can turn it into readable text whenever you wish, as was the case for Read-Host. For this reason, you can also use Get-Credential to query sensitive information that you can work on subsequently in plain text:

$logon = Get-Credential
[Runtime.InteropServices.Marshal]::`
PtrToStringAuto([Runtime.InteropServices.Marshal]::`
SecureStringToBSTR($logon.Password))
MySecretPassword

Using Special Text Commands

Often, results need to be properly output and provided with descriptions. The simplest approach doesn't require any special commands: insert the result as a variable or sub-expression directly into text and make sure that text is enclosed in double quotation marks.

# Embedding a subexpression in text:
"One CD has the capacity of $(720MB / 1.44MB) diskettes."
One CD has the capacity of 500 diskettes.

# Embedding a variable in text:
$result = 720MB / 1.44MB
"One CD has the capacity of $result diskettes."
One CD has the capacity of 500 diskettes.

More options are offered by special text commands that PowerShell furnishes from three different areas:

  • String operators: PowerShell includes a number of string operators for general text tasks, which you can use to replace text and to compare text (Table 13.2).
  • Dynamic methods: the String data type, which saves text, includes its own set of text statements that you can use to search through, dismantle, reassemble, and modify text in diverse ways (Table 13.6).
  • Static methods:finally, the String .NET class includes static methods bound to no particular text.

String Operators

The -f format operator is the most important PowerShell string operator. You'll soon be using it to format numeric values for easier reading:

"{0} diskettes per CD" -f (720mb/1.44mb)
500 diskettes per CD

All operators function in basically the same way: they anticipate data from the left and the right that they can link together. For example, you can use -replace to substitute parts of the string for other parts:

"Hello Carl" -replace "Carl", "Eddie"
Hello Eddie

There are three implementations of the -replace operator; many other string operators also have three implementations. Its basic version is case insensitive. If you'd like to distinguish between lowercase and uppercase, use the version beginning with "c" (for case-sensitive):

# No replacement because case sensitivity was turned off this time:
"Hello Carl" -creplace "carl", "eddie"
Hello Carl

The third type begins with "i" (for insensitive) and is case insensitive. This means that this version is actually superfluous because it works the same way as -replace. The third version is merely demonstrative: if you use -ireplace instead of -replace, you'll make clear that you expressly do not want to distinguish between uppercase and lowercase.

Operator Description Example
* Repeats a string "=" * 20
+ Combines two string parts "Hello " + "World"
-replace, -ireplace Substitutes a string; case insensitive "Hello Carl" -replace "Carl", "Eddie"
-creplace Substitutes a string; case sensitive "Hello Carl" -creplace "carl", "eddie"
-eq, -ieq Verifies equality; case insensitive "Carl" -eq "carl"
-ceq Verifies equality; case sensitive "Carl" -ceq "carl"
-like, -ilike Verifies whether a string is included in another string (wildcards are permitted; case insensitive) "Carl" -like "*AR*"
-clike Verifies whether a string is included in another string (wildcards are permitted; case sensitive) "Carl" -clike "*AR*"
-notlike, -inotlike Verifies whether a string is not included in another string (wildcards are permitted; case insensitive) "Carl" -notlike "*AR*"
-cnotlike Verifies whether a string is included in another string (wildcards are permitted; case sensitive) "Carl" -cnotlike "*AR*"
-match, -imatch Verifies whether a pattern is in a string; case insensitive "Hello" -match "[ao]"
-cmatch Verifies whether a pattern is in a string; case sensitive "Hello" -cmatch "[ao]"
-notmatch, -inotmatch Verifies whether a pattern is not in a string; case insensitive "Hello" -notmatch "[ao]"
-cnotmatch Verifies whether a pattern is not in a string; case sensitive "Hello" -cnotmatch "[ao]"

Table 13.2: Operators used for handling string

Formatting String

The format operator -f formats a string and requires a string, along with wildcards on its left side and on its right side, that the results are to be inserted into the string instead of the wildcards:

"{0} diskettes per CD" -f (720mb/1.44mb)
500 diskettes per CD

It is absolutely necessary that exactly the same results are on the right side that are to be used in the string are also on the left side. If you want to just calculate a result, then the calculation should be in parentheses. As is generally true in PowerShell, the parentheses ensure that the enclosed statement is evaluated first and separately and that subsequently, the result is processed instead of the parentheses. Without parentheses, -f would report an error:

"{0} diskettes per CD" -f 720mb/1.44mb
Bad numeric constant: 754974720 diskettes per CD.
At line:1 char:33
+ "{0} diskettes per CD" -f 720mb/1 <<<< .44mb

You may use as many wildcard characters as you wish. The number in the braces states which value will appear later in the wildcard and in which order:

"{0} {3} at {2}MB fit into one CD at {1}MB" `
-f (720mb/1.44mb), 720, 1.44, "diskettes"
500 diskettes at 1.44MB fit into one CD at 720MB

Setting Numeric Formats

The formatting operator -f can insert values into text as well as format the values. Every wildcard used has the following formal structure: {index[,alignment][:format]}:

  • Index: This number indicates which value is to be used for this wildcard. For example, you could use several wildcards with the same index if you want to output one and the same value several times, or in various display formats. The index number is the only obligatory specification. The other two specifications are voluntary.
  • Alignment: Positive or negative numbers can be specified that determine whether the value is right justified (positive number) or left justified (negative number). The number states the desired width. If the value is wider than the specified width, the specified width will be ignored. However, if the value is narrower than the specified width, the width will be filled with blank characters. This allows columns to be set flush.
  • Format: The value can be formatted in very different ways. Here you can use the relevant format name to specify the format you wish. You'll find an overview of available formats below.

Formatting statements are case sensitive in different ways than what is usual in PowerShell. You can see how large the differences can be when you format dates:

# Formatting with a small letter d:
"Date: {0:d}" -f (Get-Date)
Date: 08/28/2007
# Formatting with a large letter D:
"Date: {0:D}" -f (Get-Date)
Date: Tuesday, August 28, 2007
Symbol Type Call Result
# Digit placeholder "{0:(#).##}" -f $value (1000000)
% Percentage "{0:0%}" -f $value 100000000%
, Thousands separator "{0:0,0}" -f $value 1,000,000
,. Integral multiple of 1,000 "{0:0,.} " -f $value 1000
. Decimal point "{0:0.0}" -f $value 1000000.0
0 0 placeholder "{0:00.0000}" -f $value 1000000.0000
c Currency "{0:c}" -f $value 1,000,000.00 €
d Decimal "{0:d}" -f $value 1000000
e Scientific notation "{0:e}" -f $value 1.000000e+006
e Exponent wildcard "{0:00e+0}" -f $value 10e+5
f Fixed point "{0:f}" -f $value 1000000.00
g General "{0:g}" -f $value 1000000
n Thousands separator "{0:n}" -f $value 1,000,000.00
x Hexadecimal "0x{0:x4}" -f $value 0x4240

Table 13.3: Formatting numbers

Using the formats in Table 13.3, you can format numbers quickly and comfortably. No need for you to squint your eyes any longer trying to decipher whether a number is a million or 10 million:

10000000000
"{0:N0}" -f 10000000000
10,000,000,000

There's also a very wide range of time and date formats. The relevant formats are listed in Table 13.4 and their operation is shown in the following lines:

$date= Get-Date
Foreach ($format in "d","D","f","F","g","G","m","r","s","t","T", `
"u","U","y","dddd, MMMM dd yyyy","M/yy","dd-MM-yy") {
"DATE with $format : {0}" -f $date.ToString($format) }
DATE with d : 10/15/2007
DATE with D : Monday, 15 October, 2007
DATE with f : Monday, 15 October, 2007 02:17 PM
DATE with F : Monday, 15 October, 2007 02:17:02 PM
DATE with g : 10/15/2007 02:17
DATE with G : 10/15/2007 02:17:02
DATE with m : October 15
DATE with r : Mon, 15 Oct 2007 02:17:02 GMT
DATE with s : 2007-10-15T02:17:02
DATE with t : 02:17 PM
DATE with T : 02:17:02 PM
DATE with u : 2007-10-15 02:17:02Z
DATE with U : Monday, 15 October, 2007 00:17:02
DATE with y : October, 2007
DATE with dddd, MMMM dd yyyy : Monday, October 15 2007
DATE with M/yy : 10/07
DATE with dd-MM-yy : 15-10-07
Symbol Type Call Result
d Short date format "{0:d}" -f $value 09/07/2007
D Long date format "{0:D}" -f $value Friday, September 7, 2007
t Short time format "{0:t}" -f $value 10:53 AM
T Long time format "{0:T}" -f $value 10:53:56 AM
f Full date and time (short) "{0:f}" -f $value Friday, September 7, 2007 10:53 AM
F Full date and time (long) "{0:F}" -f $value Friday, September 7, 2007 10:53:56 AM
g Standard date (short) "{0:g}" -f $value 09/07/2007 10:53 AM
G Standard date (long) "{0:G}" -f $value 09/07/2007 10:53:56 AM
M Day of month "{0:M}" -f $value September 07
r RFC1123 date format "{0:r}" -f $value Fri, 07 Sep 2007 10:53:56 GMT
s Sortable date format "{0:s}" -f $value 2007-09-07T10:53:56
u Universally sortable date format "{0:u}" -f $value 2007-09-07 10:53:56Z
U Universally sortable GMT date format "{0:U}" -f $value Friday, September 7, 2007 08:53:56
Y Year/month format pattern "{0:Y}" -f $value September 2007

Table 13.4: Formatting date values

If you want to find out which type of formatting options are supported, you need only look for .NET types that support the toString() method:

[appdomain]::currentdomain.getassemblies() | ForEach-Object {
$_.GetExportedTypes() | Where-Object {! $_.IsSubclassof([System.Enum])}
} | ForEach-Object {
$Methods = $_.getmethods() | Where-Object {$_.name -eq "tostring"} |%{"$_"};
If ($methods -eq "System.String ToString(System.String)") {
$_.fullname
}
}
System.Enum
System.DateTime
System.Byte
System.Convert
System.Decimal
System.Double
System.Guid
System.Int16
System.Int32
System.Int64
System.IntPtr
System.SByte
System.Single
System.UInt16
System.UInt32
System.UInt64
Microsoft.PowerShell.Commands.MatchInfo

For example, among the supported data types is the "globally unique identifier" System.Guid. Because you'll frequently require GUID, which is clearly understood worldwide, here's a brief example showing how to create and format a GUID:

$guid = [GUID]::NewGUID()
Foreach ($format in "N","D","B","P") {
"GUID with $format : {0}" -f $GUID.ToString($format)}
GUID with N : 0c4d2c4c8af84d198b698e57c1aee780
GUID with D : 0c4d2c4c-8af8-4d19-8b69-8e57c1aee780
GUID with B : {0c4d2c4c-8af8-4d19-8b69-8e57c1aee780}
GUID with P : (0c4d2c4c-8af8-4d19-8b69-8e57c1aee780)
Symbol Type Call Result
dd Day of month "{0:dd}" -f $value 07
ddd Abbreviated name of day "{0:ddd}" -f $value Fri
dddd Full name of day "{0:dddd}" -f $value Friday
gg Era "{0:gg}" -f $value A. D.
hh Hours from 01 to 12 "{0:hh}" -f $value 10
HH Hours from 0 to 23 "{0:HH}" -f $value 10
mm Minute "{0:mm}" -f $value 53
MM Month "{0:MM}" -f $value 09
MMM Abbreviated month name "{0:MMM}" -f $value Sep
MMMM Full month name "{0:MMMM}" -f $value September
ss Second "{0:ss}" -f $value 56
tt AM or PM "{0:tt}" -f $value
yy Year in two digits "{0:yy}" -f $value 07
yyyy Year in four digits "{0:YY}" -f $value 2007
zz Time zone including leading zero "{0:zz}" -f $value +02
zzz Time zone in hours and minutes "{0:zzz}" -f $value +02:00

Table 13.5: Customized date value formats

Outputting Values in Tabular Form: Fixed Width

To display the output of several lines in a fixed-width font and align them one below the other, each column of the output must have a fixed width. A formatting operator can set outputs to a fixed width.

In the following example, Dir returns a directory listing, from which a subsequent loop outputs file names and file sizes. Because file names and sizes vary, the result is ragged right and hard to read:

dir | ForEach-Object { "$($_.name) = $($_.Length) Bytes" }
history.csv = 307 Bytes
info.txt = 8562 Bytes
layout.lxy = 1280 Bytes
list.txt = 164186 Bytes
p1.nrproj = 5808 Bytes
ping.bat = 116 Bytes
SilentlyContinue = 0 Bytes

The following result with fixed column widths is far more legible. To set widths, add a comma to the sequential number of the wildcard and after it specify the number of characters available to the wildcard. Positive numbers will set values to right alignment, negative numbers to left alignment:

dir | ForEach-Object { "{0,-20} = {1,10} Bytes" -f $_.name, $_.Length }
history.csv = 307 Bytes
info.txt = 8562 Bytes
layout.lxy = 1280 Bytes
list.txt = 164186 Bytes
p1.nrproj = 5808 Bytes
ping.bat = 116 Bytes
SilentlyContinue = 0 Bytes

String Object Methods

You know from Chapter 6 that PowerShell stores everything in objects and that every object contains a set of instructions known as methods. Text is stored in a String object, which includes a number of useful commands for working with text. For example, to ascertain the file extension of a file name, use LastIndexOf() to determine the position of the last "." character, and then use Substring() to extract text starting from the position:

$path = "c:\test\Example.bat"
$path.Substring( $path.LastIndexOf(".")+1 )
bat

Another approach uses the dot as separator and Split() to split up the path into an array. The result is that the last element of the array (-1 index number) will include the file extension:

$path.Split(".")[-1]
bat

Table 13.6 provides an overview of all the methods that include a string object.

Function Description Example
CompareTo() Compares one string to another ("Hello").CompareTo("Hello")
Contains() Returns "True" if a specified comparison string is in a string or if the comparison string is empty ("Hello").Contains("ll")
CopyTo() Copies part of a string to another string $a = ("Hello World").toCharArray()
("User!").CopyTo(0, $a, 6, 5)
$a

EndsWith() Tests whether the string ends with a specified string ("Hello").EndsWith("lo")
Equals() Tests whether one string is identical to another string ("Hello").Equals($a)
IndexOf() Returns the index of the first occurrence of a comparison string ("Hello").IndexOf("l")
IndexOfAny() Returns the index of the first occurrence of any character in a comparison string ("Hello").IndexOfAny("loe")
Insert() Inserts new string at a specified index in an existing string ("Hello World").Insert(6, "brave ")
GetEnumerator() Retrieves a new object that can enumerate all characters of a string ("Hello").GetEnumerator()
LastIndexOf() Finds the index of the last occurrence of a specified character ("Hello").LastIndexOf("l")
LastIndexOfAny() Finds the index of the last occurrence of any character of a specified string ("Hello").LastIndexOfAny("loe")
PadLeft() Pads a string to a specified length and adds blank characters to the left (right-aligned string) ("Hello").PadLeft(10)
PadRight() Pads string to a specified length and adds blank characters to the right (left-aligned string) ("Hello").PadRight(10) + "World!"
Remove() Removes any requested number of characters starting from a specified position ("Hello World").Remove(5,6)
Replace() Replaces a character with another character ("Hello World").Replace("l", "x")
Split() Converts a string with specified splitting points into an array ("Hello World").Split("l")
StartsWith() Tests whether a string begins with a specified character ("Hello World").StartsWith("He")
Substring() Extracts characters from a string ("Hello World").Substring(4, 3)
ToCharArray() Converts a string into a character array ("Hello World").toCharArray()
ToLower() Converts a string to lowercase ("Hello World").toLower()
ToLowerInvariant() Converts a string to lowercase using casing rules of the invariant language ("Hello World").toLowerInvariant()
ToUpper() Converts a string to uppercase ("Hello World").toUpper()
ToUpperInvariant() Converts a string to uppercase using casing rules of the invariant language ("Hello World").ToUpperInvariant()
Trim() Removes blank characters to the right and left (" Hello ").Trim() + "World"
TrimEnd() Removes blank characters to the right (" Hello ").TrimEnd() + "World"
TrimStart() Removes blank characters to the left (" Hello ").TrimStart() + "World"
Chars() Provides a character at the specified position ("Hello").Chars(0)

Table 13.6: The methods of a string object

Analyzing Methods: Split() as Example

You already know in detail from Chapter 6 how to use Get-Member to find out which methods an object contains and how to invoke them. Just as a quick refresher, let's look again at an example of the Split() method to see how it works.

("something" | Get-Member Split).definition
System.String[] Split(Params Char[] separator), System.String[] Split(
Char[] separator, Int32 count), System.String[] Split(Char[] separator,
StringSplitOptions options), System.String[] Split(Char[] separator,
Int32 count, StringSplitOptions options), System.String[] Split(String[]
separator, StringSplitOptions options), System.String[] Split(String[]
separator, Int32 count, StringSplitOptions options)

Definition gets output, but it isn't very easy to read. Because Definition is also a string object, you can use methods from Table 13.6, including Replace(), to insert a line break where appropriate. That makes the result much more understandable:

("something" | Get-Member Split).Definition.Replace("), ", ")`n")
System.String[] Split(Params Char[] separator)
System.String[] Split(Char[] separator, Int32 count)
System.String[] Split(Char[] separator, StringSplitOptions options)
System.String[] Split(Char[] separator, Int32 count,
StringSplitOptions options)
System.String[] Split(String[] separator, StringSplitOptions options)
System.String[] Split(String[] separator, Int32 count,
StringSplitOptions options)

There are six different ways to invoke Split(). In simple cases, you might use Split() with only one argument, Split(), you will expect a character array and will use every single character as a possible splitting separator. That's important because it means that you may use several separators at once:

"a,b;c,d;e;f".Split(",;")
a
b
c
d
e
f

If the splitting separator itself consists of several characters, then it has got to be a string and not a single Char character. There are only two signatures that meet this condition:

System.String[] Split(String[] separator,
StringSplitOptions options)
System.String[] Split(String[] separator, Int32 count,
StringSplitOptions options)

You must make sure that you pass data types to the signature that is exactly right for it to be able to use a particular signature. If you want to use the first signature, the first argument must be of the String[] type and the second argument of the StringSplitOptions type. The simplest way for you to meet this requirement is by assigning arguments first to a strongly typed variable. Create the variable with exactly the type that the signature requires:

# Create a variable of the [StringSplitOptions] type:
[StringSplitOptions]$option = "None"

# Create a variable of the String[] type:
[string[]]$separator = ",;"
# Invoke Split with the wished signature and use a two-character long separator:
("a,b;c,;d,e;f,;g").Split($separator, $option)
a,b;c
d,e;f
g

Split() in fact now uses a separator consisting of several characters. It splits the string only at the points where it finds precisely the characters that were specified. There does remain the question of how do you know it is necessary to assign the value "None" to the StringSplitOptions data type. The simple answer is: you don't know and it isn't necessary to know. If you assign a value to an unknown data type that can't handle the value, the data type will automatically notify you of all valid values:

[StringSplitOptions]$option = "werner wallbach"
Cannot convert value "werner wallbach" to type
"System.StringSplitOptions" due to invalid enumeration
values. Specify one of the following enumeration values
and try again. The possible enumeration values are
"None, RemoveEmptyEntries".
At line:1 char:28
+ [StringSplitOptions]$option <<<< = "werner wallbach"

By now it should be clear to you what the purpose is of the given valid values and their names. For example, what was RemoveEmptyEntries() able to accomplish? If Split() runs into several separators following each other, empty array elements will be the consequence. RemoveEmptyEntries() deletes such empty entries. You could use it to remove redundant blank characters from a text:

[StringSplitOptions]$option = "RemoveEmptyEntries"
"This text has too much whitespace".Split(" ", $option)
This
text
has
too
much
whitespace

Now all you need is just a method that can convert the elements of an array back into text. The method is called Join(); it is not in a String object but in the String class.

Using String Class Commands

Chapter 6 clearly defined the distinction between classes and objects (or instances). Just to refresh your memory: every String object is derived from the String class. Both include diverse methods. You can see these methods at work when you press (Tab) after the following instruction, which activates AutoComplete:

[String]::(Tab)

Get-Member will return a list of all methods. This time, specify the -Static parameter in addition:

"sometext" | Get-Member -Static -MemberType Method

You've already used static methods. In reality, the -f format operator corresponds to the Format() static method, and that's why the following two statements work in exactly the same way:

# Using a format operator:
"Hex value of 180 is &h{0:X}" -f 180
Hex value of 180 is &hB4

# The static method Format has the same result:
[string]::Format("Hex value of 180 is &h{0:X}", 180)
Hex value of 180 is &hB4

The Format() static method is very important but is usually ignored because -f is much easier to handle. But you wouldn't be able to do without two other static methods: Join() and Concat().

Join(): Changing Arrays to Text

Join() is the counterpart of Split() discussed above. Join() assembles an array of string elements into a string. It enables you to complete the above example and to make a function that removes superfluous white space characters from the string:

function RemoveSpace([string]$text) {
$private:array = $text.Split(" ", `
[StringSplitOptions]::RemoveEmptyEntries)
[string]::Join(" ", $array)
}

RemoveSpace "Hello, this text has too much whitespace."
Hello, this text has too much whitespace.

Concat(): Assembling a String Out of Several Parts

Concat() assembles a string out of several separate parts. At first glance, it works like the "+" operator:

"Hello" + " " + "World!"
Hello World!

But note that the "+" operator always acts strangely when the first value isn't a string:

# Everything will be fine if the first value is string:
"Today is " + (Get-Date)
Today is 08/29/2007 11:02:24

# If the first value is not text, errors may result:
(Get-Date) + " is a great date!"
Cannot convert argument "1", with value: " is a great date!",
for "op_Addition" to type "System.TimeSpan": "Cannot convert
value " is a great date!" to type "System.TimeSpan". Error:
"Input string was not in a correct format.""
At line:1 char:13
+ (Get-Date) + <<<< " is a great date!

If the first value of the calculation is a string, all other values will be put into the string form and assembled as requested into a complete string. If the first value is not a string—in the example, it was a date value—all the other values will be changed to this type. That's just what causes an error, because it is impossible to change "is a great date!" to a date value. For this reason, the "+" operator is an unreliable tool for assembling a string.

Concat() causes fewer problems: it turns everything you specify to the method into a string. Concat(), when converting, also takes into account your current regional settings; it will provide, for example, U.S. English date and time formats:

[string]::Concat("Today is ", (Get-Date))
Today is 8/29/2007 11:06:00 AM


[string]::Concat((Get-Date), " is a great date!")
8/29/2007 11:06:24 AM is a great date!

Simple Pattern Recognition

Recognizing patterns is a frequent task that is necessary for verifying user entries, such as to determine whether a user has given a valid network ID or valid e-mail address. Useful and effective pattern recognition requires wildcard characters that represent a certain number and type of characters.

A simple form of wildcards was invented for the file system many years ago and it still works today. In fact, you've doubtlessly used it before in one form or another:

# List all files in the current directory that
# have the txt file extension:
Dir *.txt

# List all files in the Windows directory that
# begin with "n" or "w":
dir $env:windir\[nw]*.*

# List all files whose file extensions begin with
# "t" and which are exactly 3 characters long:
Dir *.t??

# List all files that end in one of the letters
# from "e" to "z"
dir *[e-z].*

路过

雷人

握手

鲜花

鸡蛋

相关阅读

手机版|小黑屋|BC Morning Website ( Best Deal Inc. 001 )  

GMT-8, 2025-8-25 20:00 , Processed in 0.016436 second(s), 25 queries .

Supported by Best Deal Online X3.5

© 2001-2025 Discuz! Team.