Powershell Foreach не пропускает значения из массива - PullRequest
1 голос
/ 06 апреля 2019

Я пытаюсь написать скрипт, который загружает информацию с веб-сайтов.Я могу загрузить информацию, но не могу заставить работать фильтрацию.У меня есть ряд значений, которые я хочу пропустить, которые хранятся в $TakeOut, но он не распознает значения в if -eq $TakeOut.Мне нужно написать строку для каждого значения.

Мне интересно, есть ли способ использовать $value, так как со временем будет пропущено значительное количество значений.

Это работает, но в долгосрочной перспективе это не практично.

if ($R.innerText -eq "Home") {Continue}

Что-то вроде этого было бы предпочтительным.

if ($R.innerText -eq $TakeOut) {Continue}

Вот пример моего кода.

#List of values to skip
$TakeOut = @()
$TakeOut = (
"Help",
"Home",
"News",
"Sports",
"Terms of use",
"Travel",
"Video",
"Weather"
)

#Retrieve website information
$Results = ((Invoke-WebRequest -Uri "https://www.msn.com/en-ca/").Links)

#Filter and format to new table of values
$objects = @()
foreach($R in $Results) {
   if ($R.innerText -eq $TakeOut) {Continue}
   $objects += New-Object -Type PSObject -Prop @{'InnerText'= $R.InnerText;'href'=$R.href;'Title'=$R.href.split('/')[4]}
}

#output to file
$objects  | ConvertTo-HTML -As Table -Fragment | Out-String >> $list_F

1 Ответ

1 голос
/ 06 апреля 2019

Вы не можете сознательно использовать массив в качестве RHS операции -eq (массив будет неявно строковым, что не будет работать должным образом).

PowerShell имеет операторы -contains и -in для проверки членства значения в массиве (использование -eq для каждого элемента - см. этот ответ для фон); Таким образом:

 if ($R.innerText -in $TakeOut) {Continue}

Как правило, ваш код может быть оптимизирован (синтаксис PSv3 +):

$TakeOut = 
    "Help",
    "Home",
    "News",
    "Sports",
    "Terms of use",
    "Travel",
    "Video",
    "Weather"

#Retrieve website information
$Results = (Invoke-WebRequest -Uri "https://www.msn.com/en-ca/").Links

#Filter and format to new table of values
$objects = foreach($R in $Results) {
   if ($R.innerText -in $TakeOut) {Continue}
   [pscustomobject @{
      InnerText = $R.InnerText
      href = $R.href
      Title = $R.href.split('/')[4]
   }
}

#output to file
$objects | ConvertTo-HTML -As Table -Fragment >> $list_F
  • Обратите внимание на отсутствие @(...), которое никогда не требуется для литералов массива.

  • Построение массива в цикле с += является медленным (и многословным); просто используйте оператор foreach в качестве выражения, которое возвращает выходные данные тела цикла в виде массива.

  • [pscustomobject] @{ ... } - PSv3 + синтаксический сахар для создания пользовательских объектов; Помимо того, что он быстрее, чем вызов New-Object, он обладает дополнительным преимуществом сохранения порядка свойств.

Вы можете написать все это как один конвейер:

#Retrieve website information
(Invoke-WebRequest -Uri "https://www.msn.com/en-ca/").Links | ForEach-Object {
   #Filter and format to new table of values
   if ($_.innerText -in $TakeOut) {return}
   [pscustomobject @{
      InnerText = $_.InnerText
      href = $_.href
      Title = $_.href.split('/')[4]
   }
} | ConvertTo-HTML -As Table -Fragment >> $list_F

Обратите внимание на необходимость использования return вместо continue для перехода к следующему входу.

...