-
使用SelectNodes()来选择Nodes SelectNodes()方法是Xpath查询语言支持的方法,也允许你选择结点。XPath指的是一个结点‘路径名称’: 1 2 $xmldata = [xml](Get-Content employee.xml) $xmldata.SelectNodes("staff/employee") Name function age ---- -------- --- Tobias Weltner management 39 Cofi Heidecke security 4 结果看起来像前面直接通过属性访问一样,但是XPath支持在方括号中使用通配符访问。下面的语句只会返回第一个员工结点。 1 2 3 4 5 PS> $xmldata.SelectNodes("staff/employee[1]") Name function age ---- -------- --- Tobias Weltner management 39 如果你想,你还可以获取一个年龄小于18岁的员工列表: 1 2 3 4 5 PS> $xmldata.SelectNodes("staff/employee[age<18]") Name function age ---- -------- --- Cofi Heidecke security 4 类似的方式,查询语言也支持获取列表中的最后一位员工信息,所以也可以指定位置: 1 2 $xmldata.SelectNodes("staff/employee[last()]") $xmldata.SelectNodes("staff/employee[position()>1]")查看全部
-
访问和更新单个结点 如果一个结点在xml中是唯一的,你可以像前面的例子一样输入一个句号来访问它。然而,多数情况下XML文档包含了许多类似的结点(被称为兄弟结点),像前面最后一个例子中一样,包含了多个独立的员工。比如,你可以使用管道获得特定的员工,然后来更新它的数据。 1 2 $xmldata.staff.employee | Where-Object { $_.Name -match "Tobias Weltner" } Name function age ---- -------- --- Tobias Weltner management 39 1 2 3 4 $employee = $xmldata.staff.employee | Where-Object { $_.Name -match "Tobias Weltner" } $employee.function = "vacation" $xmldata.staff.employee | ft -autosize Name function age ---- -------- --- Tobias Weltner vacation 39 Cofi Heidecke security 4查看全部
-
如果你想将XML文件按照实际的XML来处理,而不是纯文本。文件的内容必须转换成XML类型。类型转换在第六章已经提到,只须一行。 1 $xmldata = [xml](Get-Content employee.xml) Get-Content从之前保存的xml文件中读取xml内容,然后使用[xml]将xml内容转换成真正的XML。你可以将xml文本直接转换成XML,然后保存在变量$xml中: 1 $xmldata = [xml]$xml 然而,转换只会在指定的xml文本合法并不包含解析错误时有效。当你尝试转换的xml文件结构不合法,会报错。 用来描述XML的结构和信息现在被存放在变量$xmldata。从现在开始,获取一小段信息将会变得非常容易,因为XML对象将每个结点转换成了属性。你可以像这样获取员工信息: 1 $xmldata.staff.employee Name Function Age ---- ----- ----- Tobias Weltner management 39 Cofi Heidecke security 4查看全部
-
(expression) 是一种简单的子表达式 (?:expression) 是一种特殊的子表达式 后者不会将子表达式的匹配结果加入组中 #示例一 PS> 'PSTips Net' -match 'PS(Tips)\b' True PS> $Matches Name Value ---- ----- 1 Tips 0 PSTips #示例二 PS> 'PSTips Net' -match 'PS(?:Tips)\b' True PS> $Matches Name Value ---- ----- 0 PSTips查看全部
-
怎样才能移除文本中多余的单词。这里,仍旧可以再次使用空格。模式可以这样定义: “\b(\w+)(\s+\1){1,}\b” 模式会搜索一个单词(以“\b”定位),它由一个单词组成(字符“\w” 和限定符“+”),白空格紧随以后(字符“\s”和限定符“?”)。该模式中,白空格字符和将要被替换的单词必须至少出现一次(至少一次或者更多次,使用限定符“{1,}”)。整个模式会被第一次出现的反向引用给替换掉,也就是位于第一个的单词。 1 2 "太多 太多 的话 我还没有说, 太多 太多 太多 的理由值得你留下" -replace "\b(\w+)(\s+\1){1,}\b", '$1' #太多 的话 我还没有说, 太多 的理由值得你留下查看全部
-
使用正则表达式可以完成一些日常任务,比如一处一个字符串中多余的白空格。模式需要描述一个空格(字符:“\s”)至少出现两次(限定符:“{2,}”)。然后以一个正常的单空格字符替换。 1 2 "太多 太多的 空格 怎么才能减少 " -replace "\s{2,}" ," " # 太多 太多的 空格 怎么才能减少查看全部
-
“替换串”可以由多行文本中的多个实例组成。例如,在你平时回复一封邮件时,你可能在新邮件中会通过在行首添加 “>” 符号来引用原邮件的中的内容。正则表达式就可以做这样的标记。 然而,要完成它,你可能得稍微了解一点“多行”模式。通常,该模式是关闭的,此时限定符”^”代表文本的开始,”$”代表文本的结束。要让这两个限定符可以代表文本行的开始和文本行的结束,必须使用”(?m)”来开启“多行”模式。只有这样,–replace 才会在每个单独的文本行之间替换模式。在“多行”模式开启后,限定符”^” 和 “\A”,还有”$” and “\Z”会顿时拥有不同的表现。”\A”仍然会标志文本的开始,而”^”则会标志文本行的开始。”\Z”仍然会标志文本的结尾,而”$”则会标志文本行结尾。 $text = @" 这是一段文本, 我想在回复的邮件中引用它, 所以我在每行的开始追加了">" 符号。 "@ 这是一段文本, 我想在回复的邮件中引用它, 所以我在每行的开始追加了">" 符号。 # 通常, -replace 没有工作在多行模式. # 鉴于此,只有第一行的开始被替换了: $text -replace "^", "> " > 这是一段文本, 我想在回复的邮件中引用它, 所以我在每行的开始追加了">" 符号。 # 如果你开启了多行模式, 替换串则会多行文本中起作用: $text -replace "(?m)^", "> " > 这是一段文本, > 我想在回复的邮件中引用它, > 所以我在每行的开始追加了">" 符号。 # 你也可以使用RegEx对象来完成多行替换, # 不过得显式指定多行模式 [regex]::Replace($text, "^", "> ", ` [Text.RegularExpressions.RegExOptions]::Multiline) > 这是一段文本, > 我想在回复的邮件中引用它, # 在多行模式中 \A 仍旧代表文本的开始,^代表行的开始 # 这就是为什么下面的方法只能替换第一行的开始 [regex]::Replace($text, "\A", "> ", ` [Text.RegularExpressions.RegExOptions]::Multiline) > 这是一段文本, 我想在回复的邮件中引用它,查看全部
-
注意:如果使用反向引用($1 $2),一定记得要使用单引号将它括起来,而不是使用双引号将它括起来查看全部
-
奇怪的是,第一个反向引用似乎并没有工作。当然原因也非常明显: “$1″ and “$2″看起来是PowerShell 变量, 但是实际上它们应当是操作符-replace的正则表达式词语。导致此结果的是你把“替换串”放在了双引号中了,PowerShell会将变量替换成具体的值,而这个值一般情况下应当为空。所以要是反向引用在“替换串”中起作用,你必须将“替换串”放置在单引号中,这样让$变成普通字符,这样PowerShell就不会把它识别为自己的变量了,并完成替换功能: 1 2 3 4 5 6 7 8 # 替换串文本必须放置单引号中,反向引用才能工作, # $2才会替换成子表达式返回的值 "Mr. Miller, Mrs. Meyer and Mr. Werner" -replace "(Mr.|Mrs.)\s*(Miller|Meyer)", 'Our client $2' # Our client Miller, Our client Meyer and Mr. Werner # 另外也可以使用转义字符 `$来标记$: "Mr. Miller, Mrs. Meyer and Mr. Werner" -replace "(Mr.|Mrs.)\s*(Miller|Meyer)", "Our client `$2" # Our client Miller, Our client Meyer and Mr. Werner查看全部
-
在一个字符串中替换了多个指定的关键字。通常效率还是挺高的,但是有时候你可能不想替换所有出现的关键字,而只是想替换出现在特殊上下文中的关键字。这样的情况下,上下文必须定义在模式中。例如,怎样更改正则表达式,让它只替换名字Miller和Meyer. 1 2 3 "Mr. Miller, Mrs. Meyer and Mr. Werner" -replace "(Mr.|Mrs.)\s*(Miller|Meyer)", "Our client" # Our client, Our client and Mr. Werner 输出结果看起来有点奇怪,但是确实是和搜索模式匹配的。被替换掉的仅仅是Mr.或者Mrs. Miller和Mr. 或者 Mrs. Meyer。词语”Mr. Werner”没有被替换。遗憾的是结果没道理替换掉整个模式,至少人名应当保留。这可能吗? 此时反向引用应当登场了。在正则表达式中,不论你什么时候使用圆括号,圆括号中的结果都是分开被评估的。你可以在你的“替换串”中使用这些分离出来的结果。第一个子表达式的结果总是”Mr.” 或者a “Mrs.”。第二个子表达式总是返回人名。词语”$1″ 和 “$2″在“替换串”中提供了你的子表达式(因此,数字是一串连续的数字;对于补充的子表达式你可以使用”$3″)。 1 2 "Mr. Miller, Mrs. Meyer and Mr. Werner" -replace "(Mr.|Mrs.)\s*(Miller|Meyer)", "Our client $2" # Our client , Our client and Mr. Werner查看全部
-
注意:使用replace并没有改变原有的变量内容,只是生成了新的内容 $a="xabc aba cad acc" $b=$a -replace "a[bd]","nn" $a $b查看全部
-
之前介绍过-replace操作符,你可以能已经知道了怎样替换字符串中的字串。让我们来回顾一下: 1 2 "Hello, PowerShell" -replace "PowerShell", "www.pstips.net" #Hello, www.pstips.net 但是这种简单的替换不可能永远都是高效的,因此可以尝试使用正则表达式来完成替换工作。下面有一个好玩的例子,用来演示它怎样实用。 也许你会碰到将多个类似的词语替换成同一个词语这样的需求。如果没有正则表达式,需要重复使用replace操作符多次。而每一次replace都会伴随一次遍历,效率明显很低。取而代之,如果使用正则表达式,则非常方便。 1 2 "Mr. Miller and Mrs. Meyer" -replace "(Mr.|Mrs.)", "Our client" # Our client Miller and Our client. Meyer 你可以在括号中输入任意的词语,多个词语之间用“|”隔开,这样所有的词语都会被指定的字符串替换掉。查看全部
-
如果你主要关心的只是规范的月份名称,你可能更喜欢获取缩写的月份名称。这也正是“??”限定符做的,它会将正则表达式转换成“非贪婪”模式,一旦他识别到一个模式,就会立即返回,不再会检查可选的子表达式是否匹配。 1 2 3 4 5 6 7 8 "Feb" -match "Feb(ruary)??" #True $matches[0] #Feb "February" -match "Feb(ruary)??" #True $matches[0] #Feb 到底限定符“??”和之前的例子中的限定符“*?”有什么联系呢?事实上“*?”不是一个独立量词。它会将“贪婪”模式转换成“非贪婪”模式。这就意味着,你可以使用“?”强制将限定符“*”转换成非贪婪模式,尽可能返回短结果。这也正是之前在匹配HTML标签时所做的。接下来你会看到假如没有“非贪婪”模式,正则表达式会尽可能检索更多的内容,也自然会出错。 1 2 3 4 5 6 7 8 9 10 # 贪婪限定符 * 会尽可能多的匹配结果: "Contents" -match "<body\b[^>]*>(.*)" #True $matches[1] #Contents<\body> #非贪婪限定符*?, 尽可能短的返回匹配结果 "Contents" -match "<body\b[^>]*>(.*?)" #True $matches[1] #Contents 根据正则表达式中的定义,HTML标签中可以匹配任意字符,而且必须以””作结,贪婪限定符会跨过第一次出现的继续匹配。但是非贪婪限定符则会在第一次匹配到结束。查看全部
-
根据正则表达式的规则,读者可能会怀疑在上一篇匹配HTML标签时,使用的事“.*?”而不是简单的“.*”。毕竟“.*”已经可以匹配足够的字符了。“.*”和“.*?”之间的不同并不容易识别。下面通过一个例子来澄清。 假设你要再一个长文件中匹配英文月份,但是月份并不是以同样的方式出现的。有时使用短格式,有时使用长格式。正如接下来看见的一样,正则表达式完成可以做到。因为正则表达式支持子表达式以可选的形式出现。 1 2 3 4 5 6 7 8 "Feb" -match "Feb(ruary)?" #True $matches[0] #Feb "February" -match "Feb(ruary)?" #True $matches[0] #February 上面两种情况正则表达式都能识别月份,但是返回的结果却不相同,一个是Feb,一个是February。默认,正则表达式属于“贪婪”模式。在搜索到Feb后会继续贪婪地搜索更多符合模式的的字符。如果可以整个文本会返回。查看全部
-
在开始匹配到的标签必须在之后也能迭代匹配到,就是要有头也得有尾,善始善终。此处你会发现引入了一个新写法””,“\1”引用的是第一个子表达式。这样就保证了HTMl标签开始的和结尾的一致了。 1 2 3 4 5 6 $regexTag = [regex]"(?i)<([A-Z][A-Z0-9]*)[^>]*>(.*?)</\1>" $result = $regexTag.Matches("<button>Press here</button>") $result[0].Groups[2].Value + " is in tag " + $result[0].Groups[1].Value <# # Press here is in tag button #>查看全部
举报
0/150
提交
取消