Убрать все строки из файла, которые соответствуют шаблону, кроме первого вхождения - PullRequest
2 голосов
/ 02 октября 2019

У меня есть каталог файлов .txt, который выглядит следующим образом:

[LINETYPE]S[STARTTIME]00:00:00
[LINETYPE]P[STARTTIME]00:00:00
[LINETYPE]B[STARTTIME]00:59:00
[LINETYPE]C[STARTTIME]00:59:00
[LINETYPE]C[STARTTIME]00:59:30
[LINETYPE]S[STARTTIME]01:00:00
[LINETYPE]P[STARTTIME]01:00:00
[LINETYPE]B[STARTTIME]01:59:00
[LINETYPE]C[STARTTIME]01:59:00
[LINETYPE]C[STARTTIME]01:59:30
[LINETYPE]S[STARTTIME]02:00:00

Я хотел бы удалить все вхождения [LINETYPE]S, кроме первого, которое всегда будет 00:00:00 и в первой строке, а затем повторно сохраните файл в новом месте.

То есть [LINETYPE]S[STARTTIME]00:00:00 должно присутствовать всегда, но другие строки, начинающиеся с [LINETYPE]S, должны быть удалены.

Это то, что я придумал, и это работает, за исключением того, что он удаляет все [LINETYPE]S строки, включая первую. Кажется, я не могу понять, как сделать эту часть после Googling, поэтому я надеюсь, что кто-то может указать мне правильное направление. Спасибо за вашу помощь!

Get-ChildItem "C:\Users\Me\Desktop\Samples" -Filter *.txt | ForEach-Object {
    Get-Content $_.FullName | Where-Object {
        $_ -notmatch "\[LINETYPE\]S"
    } | Set-Content ('C:\Users\Me\Desktop\Samples\Final\' + $_.BaseName + '.txt')
}

Ответы [ 2 ]

1 голос
/ 02 октября 2019

Я не мог понять, как это сделать с помощью конвейера [ blush ], поэтому я пошел с циклом foreach и составным тестом.

# fake reading in a text file
#    in real life, use Get-Content
$InStuff = @'
[LINETYPE]S[STARTTIME]00:00:00
[LINETYPE]P[STARTTIME]00:00:00
[LINETYPE]B[STARTTIME]00:59:00
[LINETYPE]C[STARTTIME]00:59:00
[LINETYPE]C[STARTTIME]00:59:30
[LINETYPE]S[STARTTIME]01:00:00
[LINETYPE]P[STARTTIME]01:00:00
[LINETYPE]B[STARTTIME]01:59:00
[LINETYPE]C[STARTTIME]01:59:00
[LINETYPE]C[STARTTIME]01:59:30
[LINETYPE]S[STARTTIME]02:00:00
'@ -split [System.Environment]::NewLine

$KeepFirst = '[LINETYPE]S'

$FoundFirst = $False
$FilteredList = foreach ($IS_Item in $InStuff)
    {
    if ($IS_Item.StartsWith($KeepFirst))
        {
        if (-not $FoundFirst)
            {
            $IS_Item
            $FoundFirst = $True
            }
        }
        else
        {
        $IS_Item
        }
    }

$FilteredList

output ...

[LINETYPE]S[STARTTIME]00:00:00
[LINETYPE]P[STARTTIME]00:00:00
[LINETYPE]B[STARTTIME]00:59:00
[LINETYPE]C[STARTTIME]00:59:00
[LINETYPE]C[STARTTIME]00:59:30
[LINETYPE]P[STARTTIME]01:00:00
[LINETYPE]B[STARTTIME]01:59:00
[LINETYPE]C[STARTTIME]01:59:00
[LINETYPE]C[STARTTIME]01:59:30

, в этот момент вы можете отправить новую коллекцию в файл. [ ухмылка ]

0 голосов
/ 02 октября 2019

Попробуйте выполнить следующее:

Get-ChildItem "C:\Users\Me\Desktop\Samples" -Filter *.txt |
Foreach-Object {
  $count = 0
  Get-Content $_.FullName |
    Where-Object { $_ -notmatch '\[LINETYPE\]S' -or $count++ -eq 0 } |
      Set-Content ('C:\Users\Me\Desktop\Samples\Final\' + $_.BaseName + '.txt')
}

Блок сценария, переданный Where-Object, работает в той же области, что и вызывающая программа, поэтому переменная $count может быть напрямую обновлена.

1-я строка, которая содержит содержит [LINETYPE]S , включает , потому что $count равен 0 в этой точке, после , который $count увеличивается ($count++);последующие [LINETYPE]S не включены , а не , поскольку тогда $count уже больше 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...