#arrays #powershell #string-comparison
#массивы #powershell #сравнение строк
Вопрос:
Я пытаюсь сравнить два массива: один содержит список имен пользователей (динамический, иногда больше имен пользователей, иногда меньше), а другой содержит список имен файлов (также динамический). Каждое имя файла содержит имя пользователя вместе с другим текстом, например, «Отчет об имени пользователя [дата].xlsx». Цель состоит в том, чтобы сопоставить элементы между массивом A и массивом B.
Массив A — это просто имена пользователей. Вывод массива A, содержащегося в $Username, просто: PersonA PersonB PersonC и т. Д…
Массив B содержит пути к файлам, но я могу сузить его до просто имен файлов, таких как so $arrayB.Имя (полный путь будет $arrayB.Полное имя). Формат именования для массива B — «Отчет об имени пользователя [дата].xlsx».
Вывод массива B, содержащегося в $LatestFiles.Имя (для имени файла): Отчет о персонаже 1-1-21.xlsx Отчет PersonB 1-1-21.xlsx Отчет PersonC 1-1-21.xlsx
После сопоставления последней частью будет, если элемент в массиве A совпадает с элементом в массиве B, присоедините arrayB.Полное имя к соответствующему имени пользователя «@domain.com «.
К сожалению, я даже не могу заставить соответствие работать должным образом.
Я пробовал:
foreach ($elem in $UserName) { if ($LatestFiles.Name -contains $elem) { "there is a match" } }
и
foreach ($elem in $UserName) {
if($LatestFiles.Name -contains $elem) {
"There is a match"
} else {
"There is no match"
}
}
и несколько разных вариантов, но я не могу заставить их выводить совпадения. Любая помощь приветствуется.
Комментарии:
1.
$LatestFiles |Where Name -eq $elem
чтобы получить коррелированные элементы из$LatestFiles
2. Попробовал это вместо того, что у меня есть, но, к сожалению, это не сработало.
3. Извините за отсутствие ясности, вам нужно будет поместить его внутри
foreach
цикла (поскольку он ссылается$elem
)4. Нет проблем, я предполагал, что так много lol. Если я заменю «$LatestFiles. Name -содержит $elem» в цикле foreach с вашим предложением, он ничего не выводит. Аналогично, если я заменю весь «оператор if» вашим предложением, вывод также будет пустым. Если информация о массивах недостаточно ясна, я могу добавить больше информации. Еще раз спасибо.
5. Просто перечитайте сообщение, вы захотите
... |Where Name -like "${elem}*"
, чтобы оно проверяло, начинается ли имя файла со значения$elem
Ответ №1:
Краткий ответ на вопрос, почему вы не можете получить совпадения: -Contains
предназначен для сопоставления значения с коллекцией, а не с String
. Вам было бы лучше использовать -Like
для вашего оператора сравнения. Или, по крайней мере, вы можете попытаться увидеть, находится ли имя файла, а не просто часть имени, содержащая пользователя, в коллекции имен пользователей.
Похоже, вы не просто сравниваете массивы, а более сложный вопрос о том, что вы делаете с двумя совпадающими элементами.
$LatestFiles |
ForEach-Object {
# first, let's take the formatted file name and make it more usable
$fileName = $_.BaseName -split ' ' # BaseName over Name so that it strips the extension
Write-Output @{
User = $fileName[0]
Date = $fileName[2]
File = $_
}
} -PipelineVariable FileData |
# next, only accept valid users
Where-Object User -In $UserName |
# note that we don't need the value from $UserName because we already have it in $FileData.User (what we matched)
ForEach-Object {
# finally do your thing with it.
$userWithDomain = "$($FileData.User)@domain.com"
Write-Output $userWithDomain # or whatever you want
}
Комментарии:
1. Спасибо. Это многому меня научило, в том числе переменной -PipelineVariable, которая чрезвычайно полезна для этого.