我是Powershell脚本编写的新手,但我觉得我忽略了一个简单的答案,希望你们中的一些人可以提供帮助。
我的公司从我们所有的计算机中导出文件,其中一部分位于Mapped Network Printers的中间。它看起来像这样:
-------------------------------------------------------------------------
Mapped Network Printers:
NetworkAddress\HP425DN [DEFAULT PRINTER]
-------------------------------------------------------------------------
Local Printers:
我被要求做的是将Mapped Network Printers复制到新的文本文件中。
我尝试使用带有上下文参数的Select-String,但我无法知道有多少网络打印机,所以我无法猜测。
我也尝试使用我在本网站上找到的以下代码,但它没有返回任何内容:
$MapPrint = gc C:\Users\User1\Documents\Config.txt
$from = ($MapPrint | Select-String -pattern "Mapped Network Printers:" |
Select-Object LineNumber).LineNumber
$to = ($MapPrint | Select-String -pattern "-------------------------------
--------------------------------------------" | Select-Object
LineNumber).LineNumber
$i = 0
$array = @()
foreach ($line in $MapPrint)
{
foreach-object { $i++ }
if (($i -gt $from) -and ($i -lt $to))
{
$array += $line
}
}
$array
我基本上想在“Mapped Network Printers”开始搜索并在“------”的下一行结束它
非常感谢任何帮助。
答案 0 :(得分:0)
您可以使用Select-String
或Where-Object
来查找\
的字词。更进一步,您可以使用RegEx查找server\printer
值,如下所示:
Get-Content C:\Users\User1\Documents\Config.txt -Raw |
Select-String '[A-Z0-9]+\\[A-Z0-9]+' -AllMatches |
ForEach-Object {$_.Matches.Value}
请注意,这假设服务器名称和打印机仅使用A-Z和0-9,如果这不是一个有效的假设,您可能需要查找更多字符。
以下是使用Where-Object
过滤\
Get-Content 'C:\Users\User1\Documents\Config.txt' | Where-Object {$_ -like '*\*'}
答案 1 :(得分:0)
$Doc= "C:\temp\test.txt"
$Doc_end ="C:\temp\testfiltered.txt"
$reader = [System.IO.File]::OpenText($Doc)
$cdata=""
while($null -ne ($line = $reader.ReadLine()))
{
if ($line -like ('---*') ) {$Read = 0 }
if ($Read -eq 1) {$cdata+= $line + "`r`n"}
if ($line -like ('Mapped Network Printers:*')) {$Read = 1}
}
$cdata | Out-File $Doc_end -Force
答案 2 :(得分:0)
您可以使用foreach-object
命令和一些其他测试条件执行您尝试的操作。只需在遇到Mapped Network Printers:
行时设置标记,然后在下一行-like "---*"
上终止输出就可以了,例如
## positional parameters
param(
[Parameter(Mandatory=$true)][string]$infile
)
$beginprn = 0
get-content $infile | foreach-object {
# terminate condition
if ([int]$beginprn -eq 1 -and $_ -like "---*") {
break
}
# output Mapped printers
if ([int]$beginprn -eq 1) {
write-host $_
}
# begin condition
if ($_ -eq "Mapped Network Printers:") {
$beginprn = 1
}
}
示例输入文件
-------------------------------------------------------------------------
Mapped Network Printers:
NetworkAddress\HP425DN [DEFAULT PRINTER]
NetworkAddress\HP4100N
-------------------------------------------------------------------------
Local Printers:
示例使用/输出
PS> parseprn.ps1 .\tmp\prnfile.txt
NetworkAddress\HP425DN [DEFAULT PRINTER]
NetworkAddress\HP4100N
答案 3 :(得分:0)
Select-String
没有根据内容提取范围行的功能。
最简单的方法是将文件作为一个整体读取并使用-replace
运算符通过正则表达式(正则表达式)提取范围:
$file = 'C:\Users\User1\Documents\Config.txt'
$regex = '(?sm).*^Mapped Network Printers:\r?\n(.*?)\r?\n---------------------.*'
(Get-Content -Raw $file) -replace $regex, '$1'
读取输入文件作为一个整体可能会出现问题,文件太大而无法放入内存中,但这可能不是您的担忧。
从好的方面来说,这种方法比处理循环中的行要快得多。
Get-Content -Raw
(PSv3 +)将输入文件整体读取。
内联正则表达式选项(?sm)
同时启用 m 最后一行和 s 单行选项:
m
表示^
和$
匹配每个行的开头和结尾,而不是整个输入字符串。s
表示元字符.
也匹配\n
个字符,因此.*
等表达式可用于匹配跨行 \r?\n
匹配单个换行符,包括CRLF和LF变种。
(.*?)
是捕获组(非贪婪地)捕获边界线之间的所有内容。
请注意,正则表达式匹配整个输入字符串,然后将其替换为仅在第一个(也是唯一的)捕获组中捕获的感兴趣的子字符串(范围)({{ 1}})。
假设$1
包含:
$file
以上产量:
-------------------------------------------------------------------------
Mapped Network Printers:
NetworkAddress\HP425DN [DEFAULT PRINTER]
NetworkAddress\HP426DN
-------------------------------------------------------------------------
Local Printers: