Удалить строку с помощью Power Shell, когда слово повторяется несколько раз - PullRequest
1 голос
/ 31 января 2020

file.txt:

Hello How are you 
what are you are doing?
This is great

Окончательный вывод файла:

Hello How are you
This is great

Здесь я хотел удалить всю строку, когда слово повторяется дважды или более (в строке 2 "are" повторяется дважды, поэтому я хочу удалить) в одну строку, используя либо пакетный сценарий, либо сценарий Power Shell.

Ответы [ 5 ]

1 голос
/ 01 февраля 2020

Использование оператора PowerShell switch с параметром -Regex позволяет получить краткое решение:

# Create a sample file
@'
Hello How are you 
what are you are doing?
This is great
'@ > file.txt

switch -Regex -File file.txt {
  '\b(\w+)\b.+\1' { continue } # line with duplicate words -> skip
  default { $_ } # duplicate-free line -> output
}

Чтобы отправить вышеприведенное в файл, оберните весь оператор switch в & { ... } и трубе к
Set-Content.

Приведенное выше регулярное выражение (\1) использует обратную ссылку (*1016*) на первую группу захвата ((...) ) снова сопоставить ранее найденное слово (\w+) (и использовать утверждения границы слова (\b), чтобы убедиться, что только целые слова снова сопоставляются).

PowerShell использует. NET ' s System.Text.RegularExpressions.Regex тип за кулисами - о поддерживаемых конструкциях см. краткий справочник по языку регулярных выражений . NET *1026*.

0 голосов
/ 31 января 2020

Нет regex требуется. И когда вы посмотрите на этот код через 6 месяцев, вы быстро поймете, как он работает: -)

Все, что вам нужно сделать, - это сравнить неизмененную строку ввода с версией самой себя, которая дедуплицированный список слов из той же строки ввода. Если они совпадают, двойных слов нет, поэтому выведите строку. В противном случае не выводите строку

Код

cls

$fileContent = Get-Content -LiteralPath "C:\temp\file.txt" 
$out = ""

# Step thru each line. Make a version of the line with al original words. Make a verison of the line with a deduped list of words. 
# Output the orginal line only if the line with the deduped list of words matches

foreach ($line in $fileContent)
{
    #trim leading and trailing spaces. Change all to lower case so that Select-Object -Unique acts on all words
    $line = $line.Trim().ToLower()

    #not sure if Select-Object -Unique requires a sorted list - sort it to make sure
    $lineWordsSorted = @($line.Split(" ") | Sort) 
    $uniqueLineWordsSorted = @($lineWordsSorted | Select-Object -Unique)

    if (($lineWordsSorted -join "") -eq ($uniqueLineWordsSorted -join ""))
    {
        $out += $line + [Environment]::NewLine
    }
}

Set-Content -LiteralPath "C:\temp\fileOut.txt" -Force -Value $out

Входной файл

enter image description here

Выходной файл

enter image description here

0 голосов
/ 31 января 2020

Вероятно, есть более элегантный способ сделать это. Это создает ха sh с количеством каждого уникального слова. Если все слова уникальны, выводится строка.

Get-Content './dupfile.txt' |
    ForEach-Object {
        $words = $_ -split ' '
        $allUnique = $true
        $wordhash = @{}
        foreach ($word in $words) {
            if (($word -ne '') -and ($wordhash[$word] -gt 0)) {
                $allUnique = $false
                break;
            }
            $wordhash[$word]++
        }

        if ($allUnique) { "$_" }
    }
0 голосов
/ 31 января 2020

Это способ PowerShell, который не так элегантен. Для подсчета уникальных слов в каждой строке используется Group-Object.

Get-Content file.txt | Foreach-Object {
  if (([regex]::Matches($_,'\w+').Value | Group-Object | Select-Object -Expand Count | Measure-object -Maximum).Maximum -eq 1) {
    $_ 
  }
}
0 голосов
/ 31 января 2020

РЕДАКТИРОВАТЬ: я неправильно прочитал вопрос, используя BASH или powershell вместо пакета, но я все равно оставляю свой ответ для тех, кому это может понадобиться. Извините за путаницу

Не самое элегантное решение, но с использованием строковых манипуляций bash без использования регулярных выражений:

#!/bin/bash

while read -r line; do
  found=0
  for word in $line; do
    for scan in $sentences; do
      [[ $word =~ $scan ]] && found=1
    done
  done
  [[ $found == 0 ]] && echo $line >> output.txt
  sentences="${sentences} $line"
done < file.txt

Так что в основном читайте каждую строку в файле text.txt

Установить найдено 0

Для каждого слова в строке для сканирования и для каждого найденного слова, напечатанного до сих пор, проверьте, есть ли совпадение, если да, установите значение 1

Если найдено в 0, строка вывода, иначе ничего не делать

РЕДАКТИРОВАТЬ: Вот более подробная версия, показывающая, что происходит:

#!/bin/bash

while read -r line; do
  found=0
  echo "Scanning line : $line"
  for word in $line; do
    echo "Scanning word : $word"
    for scan in $sentences; do
      [[ $word =~ $scan ]] && found=1
    done
  done
  [[ $found == 0 ]] && echo $line >> output.txt
  sentences="${sentences} $line"
  echo "Words to check : $sentences"

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