Возврат всей строки при отсутствии совпадений в подстроке Powershell (0, IndexOf)

У меня есть Powershell, который работает с почтой из папок Outlook. В большинстве электронных писем есть нижний колонтитул, начинающийся с текста "------". Я хочу сбросить весь текст после этой строки.

Я добавил выражение к Select-Object следующим образом:

$cleanser = {($_.Body).Substring(0, ($_.Body).IndexOf("------"))}
$someObj | Select-Object -Property @{ Name = 'Body'; Expression = $cleanser}

Это работает, когда IndexOf() возвращает совпадение... но когда совпадения нет, мой Select-Object выводит null.

Как я могу обновить свое выражение, чтобы оно возвращало исходную строку, когда IndexOf возвращает null?


person Adam    schedule 13.07.2019    source источник


Ответы (2)


PetSerAl, как и бессчетное количество раз, предоставил важный указатель в комментарии к вопросу:

Используйте оператор PowerShell -replace, который реализует замену строки на основе регулярных выражений, которая возвращает входную строку как есть если регулярное выражение не совпадает:

# The script block to use in a calculated property with Select-Object later.
$cleanser = { $_.Body -replace '(?s)------.*' }

Если вы хотите, чтобы ------ соответствовало только началу строки, используйте (?sm)^------.*; если вы также хотите удалить предыдущую новую строку, используйте (?s)\r?\n------.*

  • (?s) — это параметр встроенного регулярного выражения, который заставляет . также соответствовать новым строкам, так что .* эффективно соответствует всему оставшемуся тексту между строками.

  • Не указывая замещающий операнд, подразумевается '' (пустая строка), что эффективно удаляет совпадающую часть из входной строки (технически, копия исходной строки с соответствующая удаленная часть возвращается).

  • Если регулярное выражение '(?s)------.*' не соответствует, $_.Body возвращается как есть (технически возвращается сама входная строка, а не ее копия).

В результате удаляется все, что начинается с ------, если оно есть.

person mklement0    schedule 13.07.2019
comment
Рад слышать, что это было полезно, @Adam; Не за что. - person mklement0; 15.07.2019

Я согласен с @mklement0 и @PetSerAl Регулярные выражения дают лучший ответ. Ура! Регулярные выражения спешат на помощь!

Изменить: исправление моего исходного сообщения.

Следуя идеям @Adam об использовании блока сценария в выражении, вам просто нужно добавить больше логики в блок сценария, чтобы сначала проверить индекс перед его использованием:

$cleanser = {
    $index = ($_.Body).IndexOf("------");
    if($index -eq -1){
        $index = $_.Body.Length
    };
    ($_.Body).Substring(0, $index)
}

$someObj | Select-Object -Property @{ Name = 'Body'; Expression = $cleanser}
person HAL9256    schedule 13.07.2019
comment
@MathiasR.Jessen, проблема была не в том, что $_.Body не является строкой - проблема, которую с тех пор исправил HAL9256, заключалась в том, что $_.Body.IndexOf("------") вызывался только один раз, вне используемого блока скрипта $cleanser как часть вычисляемого свойства. - person mklement0; 14.07.2019
comment
Спасибо за это. Я предпочитаю менее подробный ответ и подозреваю (хотя и не проверял), что он, вероятно, также более эффективен. Спасибо, в любом случае :-) - person Adam; 14.07.2019