繁体   English   中英

PowerShell逐行读取文本文件并在文件夹中查找丢失的文件

[英]PowerShell read text file line by line and find missing file in folders

我是新手,需要一些帮助。 我有一个包含两列数据的文本文件。 一栏是供应商,一栏是发票。 我需要逐行扫描该文本文件,并查看路径中的供应商和发票是否匹配。 在路径$ Location中,第一个通配符是供应商编号,第二个通配符是发票,我希望将不匹配项输出到文本文件。

$Location = "I:\\Vendors\*\Invoices\*"
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt"
$Output ="I:\\Vendors\Missing\Missing.txt"
foreach ($line in Get-Content $txt) {
if (-not($line -match $location)){$line}
}
set-content $Output -value $Line

来自txt或csv文件的样本数据。

kvendnum    wapinvoice
000953  90269211
000953  90238674
001072  11012016
002317  448668
002419  06123711
002419  06137343
002419  06134382
002419  759208
002419  753087
002419  753069
002419  762614
003138  N6009348
003138  N6009552
003138  N6009569
003138  N6009612
003182  770016
003182  768995
003182  06133429

在以上数据中,唯一的匹配项在第二行:000953 90238674和第六行:002419 06137343

未经测试,但是这是我的处理方法:

$Location = "I:\\Vendors\\.+\\Invoices\\.+"
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt"
$Output ="I:\\Vendors\Missing\Missing.txt"
select-string -path $txt -pattern $Location -notMatch |
    set-content $Output

无需逐行浏览文件; PowerShell可以使用select-string为您执行此操作。 -notMatch参数简单地反转搜索并通过与模式不匹配的任何行发送。

select-string发出matchinfo对象流,其中包含满足搜索条件的行。 这些对象实际上包含的信息远远超过匹配行,但是幸运的是,PowerShell足够聪明,知道如何将相关项发送到set-content

正则表达式很难正确处理,但是如果您要执行这样的任务,则值得一试。

编辑

$Location  = "I:\Vendors\{0}\Invoices\{1}.pdf"
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt"
$Output  = "I:\Vendors\Missing\Missing.txt"

get-content -path $txt | 
    % {

        # extract fields from the line
        $lineItems = $_ -split "  "

        # construct path based on fields from the line
        $testPath = $Location -f $lineItems[0], $lineItems[1]

        # for debugging purposes
        write-host ( "Line:'{0}'  Path:'{1}'" -f $_, $testPath )

        # test for existence of the path; ignore errors
        if ( -not ( get-item -path $testPath -ErrorAction SilentlyContinue ) ) {
            # path does not exist, so write the line to pipeline
            write-output $_ 

        }

    } |
    Set-Content -Path $Output

我想我们毕竟必须逐行选择文件。 如果有一种更惯用的方式来做到这一点,那我就难以理解。

上面的代码在输入文件中假定格式一致,并使用-split将行分成数组。

编辑-版本3

$Location  = "I:\Vendors\{0}\Invoices\{1}.pdf"
$txt = "C:\\Users\sbagford.RECOEQUIP\Desktop\AP.txt"
$Output  = "I:\Vendors\Missing\Missing.txt"

get-content -path $txt | 
    select-string "(\S+)\s+(\S+)" | 
    %{

        # pull vendor and invoice numbers from matchinfo     
        $vendor = $_.matches[0].groups[1]
        $invoice = $_.matches[0].groups[2]

        # construct path
        $testPath = $Location -f $vendor, $invoice

        # for debugging purposes
        write-host ( "Line:'{0}'  Path:'{1}'" -f $_.line, $testPath )

        # test for existence of the path; ignore errors
        if ( -not ( get-item -path $testPath -ErrorAction SilentlyContinue ) ) {
            # path does not exist, so write the line to pipeline
            write-output $_ 
        }

    } |
    Set-Content -Path $Output

看起来-split " "在正在运行的脚本中的行为与其在命令行上的行为不同。 奇怪的。 无论如何,此版本使用正则表达式来解析输入行。 我针对原始帖子中的示例数据进行了测试,它似乎可以正常工作。

正则表达式细分如下

(     Start the first matching group
\S+   Greedily match one or more non-white-space characters
)     End the first matching group
\s+   Greedily match one or more white-space characters
(     Start the second matching group
\S+   Greedily match one or more non-white-space characters
)     End the second matching groups

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM