Powershell 筛选文件夹列表数组时遇到问题
我有一个文件夹名称的列表,它超过一百万行长,但它看起来像这样Powershell 筛选文件夹列表数组时遇到问题,powershell,Powershell,我有一个文件夹名称的列表,它超过一百万行长,但它看起来像这样 \\HOSTNAME\c$\Docs\PROD\10009991\BILLS\2018 \\HOSTNAME\c$\Docs\PROD\10009993\BILLS
\\HOSTNAME\c$\Docs\PROD\10009991\BILLS\2018
\\HOSTNAME\c$\Docs\PROD\10009993\BILLS
\\HOSTNAME\c$\Docs\PROD\10009993\BILLS\2014
\\HOSTNAME\c$\Docs\PROD\10009993\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10009993\BILLS\2016
\\HOSTNAME\c$\Docs\PROD\10009995\BILLS
\\HOSTNAME\c$\Docs\PROD\10009995\BILLS\2014
\\HOSTNAME\c$\Docs\PROD\10009995\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10009996\BILLS
\\HOSTNAME\c$\Docs\PROD\10009996\BILLS\2014
\\HOSTNAME\c$\Docs\PROD\10009996\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10009996\BILLS\2016
\\HOSTNAME\c$\Docs\PROD\10009996\BILLS\2017
\\HOSTNAME\c$\Docs\PROD\10009996\BILLS\2018
\\HOSTNAME\c$\Docs\PROD\10010006\10006
\\HOSTNAME\c$\Docs\PROD\10010006\BILLS
\\HOSTNAME\c$\Docs\PROD\10010006\10006\BILLS
\\HOSTNAME\c$\Docs\PROD\10010006\10006\BILLS\2013
\\HOSTNAME\c$\Docs\PROD\10010006\10006\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10010006\10006\BILLS\2016
\\HOSTNAME\c$\Docs\PROD\10010006\10006\BILLS\2017
\\HOSTNAME\c$\Docs\PROD\10010006\10006\BILLS\2018
\\HOSTNAME\c$\Docs\PROD\10010006\BILLS\2013
\\HOSTNAME\c$\Docs\PROD\10010006\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10010006\BILLS\2016
\\HOSTNAME\c$\Docs\PROD\10010006\BILLS\2017
\\HOSTNAME\c$\Docs\PROD\10010009\10009
\\HOSTNAME\c$\Docs\PROD\10010009\BILLS
\\HOSTNAME\c$\Docs\PROD\10010009\10009\BILLS
\\HOSTNAME\c$\Docs\PROD\10010011\10011
\\HOSTNAME\c$\Docs\PROD\10010011\BILLS
\\HOSTNAME\c$\Docs\PROD\10010011\10011\BILLS
\\HOSTNAME\c$\Docs\PROD\10010013\10013
\\HOSTNAME\c$\Docs\PROD\10010013\BILLS
\\HOSTNAME\c$\Docs\PROD\10010013\10013\BILLS
\\HOSTNAME\c$\Docs\PROD\10010013\10013\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10010013\10013\BILLS\2016
\\HOSTNAME\c$\Docs\PROD\10010013\10013\BILLS\2017
\\HOSTNAME\c$\Docs\PROD\10010013\10013\BILLS\2018
\\HOSTNAME\c$\Docs\PROD\10010013\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10010013\BILLS\2016
\\HOSTNAME\c$\Docs\PROD\10010013\BILLS\2017
\\HOSTNAME\c$\Docs\PROD\10010014\10014
\\HOSTNAME\c$\Docs\PROD\10010014\BILLS
\\HOSTNAME\c$\Docs\PROD\10010014\10014\BILLS
\\HOSTNAME\c$\Docs\PROD\10010014\10014\BILLS\2015
\\HOSTNAME\c$\Docs\PROD\10010014\10014\BILLS\2016
\\HOSTNAME\c$\Docs\PROD\10010014\10014\BILLS\2017
\\HOSTNAME\c$\Docs\PROD\10010014\BILLS\2015
基本上,我在寻找少数几个客户ID,其中8位帐号后面没有账单文件夹
所以它应该返回这一行,例如:
\HOSTNAME\c$\Docs\PROD\10010006\10006\BILLS
我知道会有很多重复的。最后,我只想要一个旧帐号子文件夹所在帐户的列表。这是我到目前为止所做的,但它不起作用。它只是打印出整个列表
$list = Get-Content "sample.txt"
foreach ($i in $list){
$parts = $i -split '\\'
if ($parts[7] -notlike '%Bills%'){
Write-Host $parts
}
}
所以我在别处找到了答案,为了避免XKCD DenverCoder9迷因
我的问题是在Powershell*中是通配符,而不是%。好的,所以您可以使用一些正则表达式。 目标是获取所有在8位之后没有票据名称的行
Get-Content "C:\Test\Fast Build\Bills_Test.txt" | ?{$_ -notmatch "[0-9]{8}.BILLS"}
让我们看看这里发生了什么事
我们获取文件的内容,然后将|逐行输出到对象,其中对象别名是?。然后确保使用-notmatch运算符(powershell中的Match检查aginst Regex,就像检查aginst通配符一样)。
在正则表达式中,我们寻找的是没有8位和[0-9]{8}的所有内容,以及带有票据的通配符 根据您的上述数据
$list -split "`r?`n" | Select-String -Pattern '(?<=\\)\d{8}(?!\\BILLS)'|
ForEach-Object {$_.Matches.Groups[0].Value} |
Sort-Object -Unique
通过将正则表达式与
(?事实上,的主要问题是错误地使用%
而不是*
来匹配任何字符序列,包括无通配符元字符
但是,还有其他值得改进的地方
:
- 对于大文件,不要使用
将行数组一次读入内存,而是使用PowerShell的管道通过管道连接到$list=Get Content“sample.txt”
cmdlet,逐个处理行ForEach对象
- 不要使用
输出结果;这样做只会写入控制台,您将无法捕获数据以供以后处理;相反,请使用Write Host
或最好使用隐式输出Write output
- 您不需要严格地使用通配符表达式来匹配
路径组件-您只需要在使用文本字符串与BILLS
进行比较之前从末尾修剪尾随空格BILLS'
Get-Content sample.txt | ForEach-Object {
$parts = $_ -split '\\'
if ($parts[7].TrimEnd() -ne 'BILLS') { $parts[6] }
}
$parts[6]
是帐号-请注意,通过不将其分配给变量或将其重定向到其他位置,它是隐式输出的,因此循环只返回请求的帐号
上述方法是内存有效的,但可能很慢。 如果这是一个问题,请直接使用.NET Framework阅读这些行
[IO.File]::ReadLines("$PWD/sample.txt") | ForEach-Object {
$parts = $_ -split '\\'
if ($parts[7].TrimEnd() -ne 'BILLS') { $parts[6] }
}
你只是想得到那些写着账单的,还是想得到那些以账单结尾的……我很困惑。明确地说:“我在寻找少数几个客户ID,那里没有一个账单文件夹跟在8位数的账号后面。”但是,它是否总是在8位之后有另一组数字,还是会有随机字符串?我不确定您的脚本是如何完成任务的,因为我得到了一些条目,比如“主机名c$Docs PROD 10010009 BILLS”,这就是您清楚地说的“在8位帐号之后没有BILLS文件夹”
[IO.File]::ReadLines("$PWD/sample.txt") | ForEach-Object {
$parts = $_ -split '\\'
if ($parts[7].TrimEnd() -ne 'BILLS') { $parts[6] }
}