【问题标题】:Powershell ForEach-Object lines in a text file Split compare and delete文本文件中的Powershell ForEach-Object行拆分比较和删除
【发布时间】:2018-12-31 22:59:28
【问题描述】:

我正在开发一个 Powershell 脚本,该脚本可以将文本文件中的行放入列表框中,但仅限于以日期开头的行 ../../.... 添加列表框部分正在工作。但我喜欢先从文本文件中删除旧行。 我试过这个,但它不正确。谁能帮我正确编码。

我将重新表述这个问题,希望它更清楚。

文本文件如下所示:

文本.txt

//Regular Roster | Only update if making a permanent change.
!The order for the entry must be: Day time,number,name,email(optional)
!With a comma ‘,’ separating the values.

Monday 9AM-2PM,0400499449,BILL
Monday 2PM-6PM,074477464,Terry
Monday 6PM-9PM,040484747,Leanne

Tuesday 9AM-2PM,07123456,BILL
Tuesday 2PM-6PM,054647383,Barbara
Tuesday 6PM-9PM,03937464,Mandy

//Changes to Regular Roster. This section will override the above.
!The date order of the entries below is not important but each line must follow this pattern:
!date(Dayxx/Monthxx/Yearxxxx),time(9AM,2PM or 6PM),number,name,email(optional)
!Date slash must be forward facing '/'.
!The only times that can be entered are 9AM,2PM or 6PM.
!With a comma ‘,’ separating the values.

01/01/2019,6AM,0400012345,Kurt,kurt@outlook.com
02/01/2019,6AM,0412345676,Bill,bill@outlook.com
03/01/2019,6AM,0400012345,Sam,Sam@outlook.com
04/01/2019,6AM,0412345676,Barry,barry@outlook.com
05/01/2019,6AM,0400012345,Kurt,kurt@outlook.com

如果我假设当前日期为 04/01/2019(2019 年 1 月 4 日)在 Powershell 中尝试此代码,则它可以正常工作

$CurrentDate = "04/01/2019"
$Text = "05/01/2019,6AM,0400012345,Kurt,kurt@outlook.com"
$Text | ForEach-Object {
    $Roster1Date,$Roster2Time,$Roster3Number,$Roster4Name,$Roster5Email = $_.split(",")
    $Newdate = "$Roster1Date"
    $CurrentDate = [datetime]::ParseExact("$CurrentDate", 'dd/MM/yyyy', $null)
    $Newdate = [datetime]::ParseExact("$Newdate", 'dd/MM/yyyy', $null)
    if ($Newdate -ge $CurrentDate) {
     write-output "NewDate is bigger than or equal to"
    }
    else {
      write-output "CurrentDate is bigger"
    }
};

当我尝试用这条线构建一个列表框时,它工作正常

#Add Listbox
$ShiftsListBox = New-Object System.Windows.Forms.ListBox
$ShiftsListBox.Location = New-Object System.Drawing.Size(400,40)
$ShiftsListBox.Size = New-Object System.Drawing.Size(360,20)
$ShiftsListBox.Height = 160
Get-Content $RosterPath | select-string -Pattern '../../...' | ForEach-Object {[void] $ShiftsListBox.Items.Add($_)};
$FormCreateNewShift.Controls.Add($ShiftsListBox)

当我试图将两者结合起来时,它只是空白

#Add Listbox
$TextFile = text.txt
$ShiftsListBox = New-Object System.Windows.Forms.ListBox
$ShiftsListBox.Location = New-Object System.Drawing.Size(400,40)
$ShiftsListBox.Size = New-Object System.Drawing.Size(360,20)
$ShiftsListBox.Height = 160
Get-Content $TextFile | select-string -Pattern '../../...' | ForEach-Object {
    $Roster1Date,$Roster2Time,$Roster3Number,$Roster4Name,$Roster5Email = $_.split(",")
    $Newdate = "$Roster1Date"
    $CurrentDate = [datetime]::ParseExact("$CurrentDate", 'dd/MM/yyyy', $null)
    $Newdate = [datetime]::ParseExact("$Newdate", 'dd/MM/yyyy', $null)
    if ($Newdate -ge $CurrentDate) {
     [void] $ShiftsListBox.Items.Add($_)
    }
    else {
    }
};
$FormCreateNewShift.Controls.Add($ShiftsListBox)

这个想法是,如果日期大于或等于当前日期,则在列表框中显示该行,否则不显示。但是我会尝试通过添加替换行来删除该行。

#Add Listbox
$TextFile = text.txt
$ShiftsListBox = New-Object System.Windows.Forms.ListBox
$ShiftsListBox.Location = New-Object System.Drawing.Size(400,40)
$ShiftsListBox.Size = New-Object System.Drawing.Size(360,20)
$ShiftsListBox.Height = 160
Get-Content $TextFile | select-string -Pattern '../../...' | ForEach-Object {
    $Roster1Date,$Roster2Time,$Roster3Number,$Roster4Name,$Roster5Email = $_.split(",")
    $Newdate = "$Roster1Date"
    $CurrentDate = [datetime]::ParseExact("$CurrentDate", 'dd/MM/yyyy', $null)
    $Newdate = [datetime]::ParseExact("$Newdate", 'dd/MM/yyyy', $null)
    if ($Newdate -ge $CurrentDate) {
     [void] $ShiftsListBox.Items.Add($_)
    }
    else {
          ((Get-Content -path $TextFile) -replace $_,"") | Set-Content -Path $TextFile;
    }
};
$FormCreateNewShift.Controls.Add($ShiftsListBox)

【问题讨论】:

    标签: powershell foreach text-files


    【解决方案1】:

    根据新的示例文件,此脚本区分

    • 在带有前导日期的行之间
      • 今天或以后的日期(保留)
      • 今天之前的日期(跳过)
    • 其他线路(保留)

    ## Q:\Test\2019\01\01\SO_53992011.ps1
    $Rosterpath = ".\rosterpath"
    
    $CurrentDate = (Get-Date).Date  # to have a datetime starting today at 00:00:00
    
    $RegEx = [RegEx]"^(?<day>\d{2})\/(?<mon>\d{2})\/(?<year>\d{4})"
    
    $UpdatedContent = Get-Content $RosterPath | ForEach-Object {
        If ($_ -match $RegEx){
            If((Get-Date -Year $Matches.year -Month $Matches.mon -Day $Matches.day) -ge $CurrentDate){
                # yes keep this line
                $_
            } else { 
                #drop this line
            }
        } else {
            # line without a date, keep
            $_
        }
    }
    
    $UpdatedContent | Set-Content $RosterPath
    

    【讨论】:

    • 请不要。我建议从一个新的问题开始,其中包含一个经过净化的真实世界输入文件、您所期望的描述以及您的脚本的 minimal reproducible example。并删除此问题,除非筛选所有 cmets,否则任何人都无法/不会遵循。
    • 我将删除我所有的 cmets(并建议您也这样做)并尽快在我的答案中尝试不同的方法。
    • 谢谢,我只是有一个问题,如果文件中没有任何未来的班次,如果文件中只有上面的旧班次,它不会删除它们但有人指出为空管道中的值被跳过,这意味着没有任何内容写入输出文件,因此输出文件保持不变。您可以通过将变量传递给参数 -Value 来避免此问题。将$UpdatedContent | Set-Content $RosterPath 更改为Set-Content -Value $UpdatedContent -Path $RosterPath
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多