Проблема с использованием массива, содержащего критерии с подстановочными знаками - PullRequest
1 голос
/ 31 октября 2019

Я пытался запустить код powershell, чтобы разделить файл на 2.

У меня есть пара регулярных массивов, которые прекрасно работают. 3-й массив содержит символы подстановки для каждого из критериев, и это не работает вообще.

Я пробовал -в-нет, -подобно-не похоже, -содержит -не-содержит, -соответствие -соответствие, я не получаю желаемых результатов.

    $NonAutoStructure = @("Not_Found", "UK Training Centre", "IRISH Training Centre", "Head Office", "UK Newmedica")
$AutoJournalDescriptions = @("STORE TRANFrom *",  "*SALES BANKED*")#, "*/* CREDIT" , "BANKING DIFF*BQ*" , "*/* MASTERCARD/VISA")  
$InactiveStores = @("4410", "0996", "1015", "5996")


$NonAutoJournalCompanies = {$_.Description -notcontains $AutoJournalDescriptions} 
$AutoJournalCompanies = {$_.Description -contains $AutoJournalDescriptions}
#$NonAutoJournalCompanies = {$_.structure -in $NonAutoStructure -or $_.Company -in $InactiveStores -and  $_.Amount -ne "0.00"}
#$AutoJournalCompanies = {$_.structure -notin $NonAutoStructure-and $_.Company -notin $InactiveStores -and  $_.Amount -ne "0.00"}

$UNREC_S0 | Where-Object $NonAutoJournalCompanies | Export-Csv \\774512-LRBSPT01\*****$\uardata\rt1\BankRec\Test\step1\TestNonAutoJournal.txt -notype
$UNREC_S0 | Where-Object $AutoJournalCompanies | Export-Csv \\774512-LRBSPT01\*****$\uardata\rt1\BankRec\Test\step1\TestAutoJournal.txt -notype
$UNREC_S0 | Where-Object $ZeroValuelines | Export-Csv \\774512-LRBSPT01\*****$\uardata\rt1\BankRec\Test\step1\TestZeroLines.txt -notype

Массив, с которым у меня проблемы, - это $ AutoJournalDescription. Я могу заставить его работать, только если массив содержит один критерий. В противном случае, кажется, игнорировать их всех. Здесь он содержит только пару, но критерии после # также должны быть включены. Я пытаюсь включить и исключить эти критерии как часть файлов # (Non) AutojournalCompanies, чтобы все данные были предварительно отсортированы, но разделены и затем могли быть направлены к различным потокам процессов.

Возможно, я просто пытаюсь использовать функцию, которая не предназначена для такой работы ...? Я искал решение весь день безрезультатно. Я мог бы ввести все эти критерии по отдельности в критерии создания файла, но это делает его тяжелым для чтения и неудобным для обслуживания. Я бы предпочел обогащать / модифицировать массив, когда требуются изменения.

Я надеюсь, что все имеет смысл. Я довольно новичок в powershell.

Большое спасибо,

Антуан

1 Ответ

0 голосов
/ 31 октября 2019
  • Чтобы сопоставить шаблоны с подстановочными знаками (например, *SALES BANKED*), вам необходим оператор -like;напротив, -contains выполняет равенство сравнений (неявное -eq с каждым элементом массива).

  • В то время как эти операторы (наряду с другими, например * 1015)* и -match) поддерживают массив значений input [1] , операнд сравнения (обычно RHS) должен быть скаляр (одно значение) - вы не можете сравнивать входной массив с несколькими значениями одновременно.


InВ вашем сценарии лучше всего использовать регулярные выражения ( регулярные выражения ) вместо подстановочных выражений и объединить их в одиночное регулярное выражение с оператором чередования (|), поэтому вы можете использовать одну операцию -match для проверки нескольких шаблонов:

# Sample input
$UNREC_S0  = [pscustomobject] @{ Description = 'A SALES BANKED baz' }, 
             [pscustomobject] @{ Description = 'bar' }, 
             [pscustomobject] @{ Description = 'STORE TRANFrom foo' }, 
             [pscustomobject] @{ Description = 'unrelated' }

# The filtering criteria: *regexes* to match against the descriptions,
# combined into a single regex with the alternation operator, '|'
$AutoJournalDescriptions = '^STORE TRANFrom ', 'SALES BANKED' -join '|'

# Construct script blocks to use with `Where-Object` below.
$NonAutoJournalCompanies = { $_.Description -notmatch $AutoJournalDescriptions } 
$AutoJournalCompanies =    { $_.Description -match $AutoJournalDescriptions}

$UNREC_S0 | Where-Object $NonAutoJournalCompanies | Export-Csv \\774512-LRBSPT01\*****$\uardata\rt1\BankRec\Test\step1\TestNonAutoJournal.txt -notype
# ...

Вышеприведенные данные приводят следующие данные CSV, показывая, что только описания не соответствующие регулярные выражения были экспортированы:

"Description"
"bar"
"unrelated"

Обратите внимание, как регулярное выражение ^STORE TRANFrom соответствует wildcaВыражение rd STORE TRANFrom * и SALES BANKED до *SALES BANKED*.

Подстановочный оператор * - который обычно соответствует .* в регулярном выражении - не требуется в регулярных выражениях здесь, потому чтоОператор -match неявно выполняет сопоставление подстроки (тогда как сопоставление с подстановочными знаками с -like сопоставляется с целом строкой ввода).


Необязательное чтение: фильтрациямассив строковых значений в виде массива подстрок или шаблонов:

Если вы сформулируете свои критерии как регулярные выражения (регулярные выражения), вы можете использовать Select-String cmdlet , который поддерживает поддержку нескольких операндов сравнения:

# Sample input
$descriptions = 'A SALES BANKED baz', 'bar', 'STORE TRANFrom foo', 'unrelated'

# The filtering criteria: *regexes* to match against the descriptions.
$descriptionRegexes = '^STORE TRANFrom ', 'SALES BANKED'

($descriptions | Select-String -Pattern $descriptionRegexes).Line

Примечание: Вы можете также использовать эту технику для нахождения литеральных подстрок с помощьюиспользуя -SimpleMatch вместо -Pattern, но обратите внимание, что подстроки затем сопоставляются в любом месте в каждой входной строке, не имея возможности ограничить совпадение, скажем, с началом строки.

Выше приведен вывод following (массив из 2 элементов):

A SALES BANKED baz
STORE TRANFrom foo

Вы можете использовать аналогичный подход путем объединения отдельных регулярных выражений в один с чередованием (|) оператор , который позволяет использовать оператор -match :

# Sample input
$descriptions = 'A SALES BANKED baz', 'bar', 'STORE TRANFrom foo', 'unrelated'

# The filtering criteria: *regexes* to match against the descriptions,
# combined into a single regex with the alternation operator, '|'
$descriptionRegex = '^STORE TRANFrom ', 'SALES BANKED' -join '|'
# -> '^STORE TRANFrom |SALES BANKED'

$descriptions -match $descriptionRegex

Вы также можете адаптировать этот подход к буквенной подстроке соответствие , а именно экранирование подстрок для буквального использования внутри регулярного выражения с [regex]::Escape();например,
$descriptionRegex = ('yes?', '2.0').ForEach({ [regex]::Escape($_) }) -join '|'


В противном случае, , если вам нужна поддержка подстановочный знак , вам придется - неэффективно - циклы вложений (см. Ярлык ниже, если вы можете сделать определенные предположения):

# Sample input
$descriptions = 'A SALES BANKED baz', 'bar', 'STORE TRANFrom foo', 'unrelated' 

# The filtering criteria: wildcard patterns to match against the descriptions.
$descriptionWildcards = 'STORE TRANFrom *', '*SALES BANKED*'

foreach ($descr in $descriptions) {
  foreach ($wildcard in $descriptionWildcards) {
    if ($descr -like $wildcard) { $descr; break }
  }
}

Обратите внимание, что я использовал foreach операторов вместо конвейера с ForEach-Object командлет вызов;первый работает быстрее, последний может поддерживать постоянное потребление памяти, если ввод потоковый ;с массивами, уже находящимися в памяти, полностью, оператор foreach является лучшим выбором.


Вы можете использовать ярлык , ЕСЛИ вы можете сделать два предположения :

  • Нет совпадений с одним шаблоном более чем один ввод.

  • Порядок ввода не должен бытьсохранились;то есть допустимо, чтобы порядок вывода описаний отражал порядок записей в массиве шаблонов, а не порядок описаний ввода.

# Sample input
$descriptions = 'A SALES BANKED baz', 'bar', 'STORE TRANFrom foo', 'unrelated' 

# The filtering criteria: wildcard patterns to match against the descriptions.
$descriptionWildcards = 'STORE TRANFrom *', '*SALES BANKED*'

# Loop over the criteria and match the descriptions against each.
# `foreach` is the built-in alias for the `ForEach-Object` cmdlet.
# The output order will be reflect the order of the wildcard patterns.
$descriptionWildcards | foreach { $descriptions -like $_ }

В этомВ случае, когда результирующие элементы одинаковы, их порядок отличается:

STORE TRANFrom foo
A SALES BANKED baz

[1] С массивом значений в качестве входных данных эти операторы действуют как filters : то есть они возвращают подмассив соответствующих значений;например, 1, 2, 3 -eq 2 возвращает 2 в виде одноэлементного массива.

...