簡體   English   中英

使用包含通配符條件的數組時出現問題

[英]Issue using an array containing criteria with wildcards

我一直在嘗試運行 powershell 代碼將文件拆分為 2。

我有幾個普通的 arrays,效果很好。 第三個數組包含每個條件的通配符,這根本不起作用。

我試過 -in -notin、-like -notlike、-contains -notcontains、-match -notmatch,我沒有得到我想要的結果。

    $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

我遇到問題的數組是 $AutoJournalDescriptions。 如果數組包含一個標准,我只能讓它工作。 否則,它似乎忽略了它們。 這里它只包含一對,但 # 之后的標准也應該包括在內。 我試圖將這些標准作為#(Non)AutojournalCompanies 文件的一部分包含和排除,以便所有數據都被保留,但可以分開,然后可以定向到不同的流程流。

也許我只是想使用一個不應該那樣工作的 function ......? 我整天都在尋找解決方案,但無濟於事。 我可以在文件制作標准中單獨鍵入所有這些標准,但這會使閱讀變得繁重且維護起來很麻煩。 我更願意在需要更改時豐富/修改數組。

我希望一切都說得通。 我對 powershell 很陌生。

非常感謝,

安托萬

  • 為了匹配通配符模式(例如*SALES BANKED* ),您需要-like運算符; 相比之下, -contains執行相等比較(隱式-eq針對每個數組元素)。

  • 雖然這些運算符(以及其他運算符,例如-eq-match )支持輸入值數組[1] ,但比較操作數(通常是 RHS)必須是標量(單個值) - 您無法比較輸入數組同時針對多個值。


在您的場景中,您最好的選擇是使用正則表達式正則表達式)而不是通配符表達式,並將它們與交替運算符( | )組合成一個正則表達式,因此您可以使用單個-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如何對應於通配符表達式STORE TRANFrom * ,以及SALES BANKED BANKED 對應於*SALES BANKED*

通配符*運算符 - 通常對應於正則表達式中的.* - 在此處的正則表達式中不需要,因為-match運算符隱式執行substring匹配(而通配符匹配與-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 ,但請注意,子字符串隨后會匹配每個輸入字符串中的任何位置,而不能將匹配限制在字符串的開頭.

以上輸出以下內容(一個 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

您還可以將此方法調整為文字 substring匹配,即通過escaping在帶有[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 cmdlet調用的管道; 前者更快,后者可以在輸入流式傳輸時保持 memory 消耗恆定; arrays 已經在 memory 中,完整地說, foreach語句是更好的選擇。


如果你可以做兩個假設,你可以走捷徑

  • 沒有一個通配符模式匹配多個輸入。

  • 不需要保留輸入順序; 也就是說,output 的描述順序反映了通配符模式數組中條目的順序,而不是輸入描述的順序是可以接受的。

# 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] 以一組值作為輸入,這些運算符的作用類似於過濾器:也就是說,它們返回匹配值的子數組 例如, 1, 2, 3 -eq 2返回2作為單元素數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM