Powershell: я не могу удалить строку из текстового файла - PullRequest
1 голос
/ 04 апреля 2020

Вот метод для удаления строки, которая, как я думал, будет работать

#earlier in the script
$inFile = Get-Content -Path ".\input.txt"

# ...Later... #

$inFile = Get-Content -path ".\input.txt" | where-object {$_ -notmatch $line}
set-content -path ".\input.txt" -Value $inFile

Проблема в том, что параметр -notmatch, похоже, не работает. Командлет Get-Content просто копирует весь контент из input.txt, включая $ line. Я также попытался изменить код, чтобы очистить $ inFile и создать временный держатель, но без кубиков.

Clear-Variable -name "inFile"
$holder = Get-Content -path ".\input.txt" | where-object {$_ -notmatch $line}
set-content -path ".\input.txt" -Value $holder
$inFile = Get-Content -path ".\input.txt"

Я неправильно использую -notmatch? Вот полнотекстовый скрипт для контекста.

Write-Host "Starting"

[bool] $keepRunning = 1
[bool] $everFound = 0
[bool] $searchComplete = 0
:main while($keepRunning)
{
    $inFile = Get-Content -path ".\input.txt"
    $completed = Get-Content -Path ".\output.txt"
    $line = $inFile[0]
    $holder
    if($inFile.count -eq 1)
    {
        $line = $inFile
    }

    # create condition to check if $line matches any line in completed.txt
    # if it does, skip this line and move on to the next line
    :search while($everFound -eq 0 -and $searchComplete -eq 0)
    {
        #Write-Host "Outer loop"
        foreach($url in $completed)
        {
            #Write-Host $line
            #write-host $url

            if ($line -eq $url)
            {
                Write-Host "`nThis file was already downloaded --Skipping to the next line"
                $inFile = Get-Content -path ".\input.txt" | where-object {$_ -notmatch $line}
                set-content -path ".\input.txt" -Value $inFile
                $inFile = Get-Content -path ".\input.txt"
                $line = $inFile[0]
                $everFound = 1
                break
            }
        }
        if ($everFound -eq 1)
        {
            break
        }
        $searchComplete = 1
        Write-Host "Search Complete`n"
    }
    Write-Host "Before the download--------"

    Write-Host $everFound
    Write-Host $searchComplete

    if ($everFound -eq 0 -and $searchComplete -eq 1)
    {
        #download the files
        $downloadCommand = "youtube-dl.exe --verbose --cookies .\cookies.txt `"$line`""
        get-date
        invoke-Expression $downloadCommand

        #delete the url
        add-content -Path ".\output.txt" -Value $line
        $inFile = Get-Content -path ".\input.txt" | where-object {$_ -notmatch $line} 
        set-content -path ".\input.txt" -Value $inFile
        write-host "`n"

        get-date
        Write-Host "Sleeping for 45mins"
        #start-sleep -s 2700
    }
    $everFound = 0
    $searchComplete = 0
    Write-Host "-------------After the download!!"
    Write-Host $everFound
    Write-Host $searchComplete

    # check if the file is empty. If it is, set the keepRunning flag to false and exit the main while loop
    if($Null -eq $inFile)
    {
        $keepRunning = 0
    }
}

Write-Host "Done"
Read-Host "Press the Enter Key to Exit"

EDIT: $ inFile содержит список URL-адресов YouTube в каждой строке. $ line присваивается значение первой строки $ inFile

$line = $inFile[0]

Вот URL-адрес YouTube: https://www.youtube.com/watch?v=sB5zlHMsM7k

Я также добавил несколько операторов для вывода значений $ line right перед файлом. Кто-нибудь, пожалуйста, укажите мне правильное направление.

1 Ответ

2 голосов
/ 04 апреля 2020

Я неправильно использую -notmatch?

Вы используете его неправильно, если $line содержит подстроку для поиска буквально (as- дословно) в строках входного файла, и эта подстрока содержит метасимволы регулярных выражений , такие как . и $.

Для использования -match / -notmatch для буквального соответствия подстроки необходимо escape подстроки:

$_ -notmatch [regex]::Escape($line)

Если вы хотите сопоставить только строки в полном объеме , вы должны anchor регулярное выражение:

$_ -notmatch ('^' + [regex]::Escape($line) + '$')

Обратите внимание, что PowerShell не имеет оператора для литерального соответствия подстроки.

Однако * 1036 Тип *System.String ([string]) имеет метод .Contains() для сопоставления литеральной подстроки, но не так, в отличие от операторов PowerShell, он чувствителен к регистру по умолчанию (существуют перегрузки для сопоставление без учета регистра):

-not $_.Contains($line) # case-sensitive, literal substring matching

# case-INsensitive, literal substring matching
-not $_.Contains($line, 'CurrentCultureIgnoreCase') 

Для сопоставления с полной строкой:

-not ($_.Length -eq $line.Length -and $_.Contains($line))

Преимущество использования .Contains() состоит в том, что он pe rforms лучше, чем -match, хотя последний предлагает гораздо большую гибкость.

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