Как разбить строку, содержащую новые строки - PullRequest
1 голос
/ 11 июля 2020

Строка (извлеченная из тела сообщения электронной почты Outlook .innerText) содержит встроенные символы новой строки. Как я могу разбить это на массив строк?

Я ожидал бы, что эта строка примера будет разбита на массив из двух (2) элементов. Вместо этого он становится массивом из трех (3) элементов с пустой строкой посередине.

PS C:\src\t> ("This is`r`na string.".Split([Environment]::NewLine)) | % { $_ }
This is

a string.
PS C:\src\t> "This is `r`na string.".Split([Environment]::NewLine) | Out-String | Format-Hex

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   54 68 69 73 20 69 73 20 0D 0A 0D 0A 61 20 73 74  This is ....a st
00000010   72 69 6E 67 2E 0D 0A                             ring...

Ответы [ 3 ]

3 голосов
/ 11 июля 2020

Это связано с тем, что метод .Split() разделится на любой из найденных символов, например:

"first part of a string-*second part of a string".Split("-*")

Вывод:

first part of a string

second part of a string

Дополнительный элемент - вставленная пустая строка между двумя разделенными символами.

(кредит @ mklement0, чтобы исправить это)

Так что я могу только предположить, что это результат нескольких факторов. Первый [Environment]::NewLine - это оба символа CarrigeReturn и LineFeed, и строка, исходящая из Outlook, действительно использует эту последовательность окончания строки. Все, чего следует ожидать в Windows.

Есть 2 решения, о которых я могу думать:

Вариант 1:

.Split([Environment]::NewLine), [Stringsplitoptions]::RemoveEmptyEntries)

Это очевидно придерживается того же метода .Split(), но добавленный параметр уничтожит лишний элемент.

Вариант 2:

Используйте оператор PowerShell -split, который соответствует разделить разделитель с использованием RegEx:

"This is`r`na string." -split "`r`n"
3 голосов
/ 11 июля 2020

Чтобы обработать последовательность CRLF в целом в качестве разделителя, проще использовать оператор -split , который равен regex -based:

PS> "This is `r`n`r`n a string." -split '\r?\n'
This is 
 a string.

Примечание:

  • \r?\n соответствует как CRLF (Windows -стиль), так и LF-only (Unix - style) новые строки; используйте \r\n, если вы действительно хотите сопоставить только последовательности CRLF.

    • Обратите внимание на использование строки в одинарных кавычках ('...'), чтобы передать строку содержащий регулярное выражение как есть до механизма. NET regex; механизм регулярных выражений использует \ в качестве escape-символа; следовательно, использование \r и \n.
  • Оператор -split PowerShell в целом является лучшей альтернативой [string]. NET тип .Split() метод - см. этот ответ .

Что касается того, что вы пробовали :

Аргумент разделителя [Environment]::NewLine в Windows - это строка "`r`n", то есть последовательность CRLF.

  • В PowerShell [Core] v6 + ваша команда работает , потому что эта строка в целом считается разделителем.

  • В Windows PowerShell , как Стивен указывает в своем полезном ответе , отдельные символы - CR и LF отдельно считаются разделителями, в результате чего в результирующем массиве появляется лишний пустой элемент - пустая строка между CR и LF.

Это изменение в поведении произошло вне контроля PowerShell:. NET Core представил новую перегрузку метода .Split() с параметром разделителя с типом [string], который алгоритм разрешения перегрузки PowerShell теперь выбирает вместо старой перегрузки с параметром с типом [char[]]. Предотвращение таких неизбежных (хотя и редких) непреднамеренных поведенческих изменений - еще одна веская причина предпочесть встроенный в PowerShell -split оператор , а не. NET [string] тип .Split() метод .

0 голосов
/ 12 июля 2020

Привет,

Я большой NooB в PowerShell, но ... Я написал это

$str_1 ="This is

a string."
$splt_1=$str_1.Split()
$cnt_1=1
foreach ($item in $splt_1) {
     $regEx="[a-zA-Z]"
     if ($item -cmatch $regEx){
          $Result_1=$Result_1+"$item "
     } elseif ($cnt_1 -eq 1) {
          $Result_1=$Result_1+"| "
          $cnt_1=$cnt_1+1
     }
}
Write-Host $Result_1
## OUTPUT ##
# This is | a string.

$str_2="
This is

....a st

ring...
"
$splt_2=$str_2.Split()
$cnt_2=1
foreach ($item in $splt_2) {
     $regEx="[a-zA-Z]"
     if ($item -cmatch $regEx){
          $cnt_2=1
          $Result_2=$Result_2+"$item "
     } elseif ($cnt_2 -eq 1) {
          $Result_2=$Result_2+"| "
          $cnt_2=$cnt_2+1
     }
}
Write-Host $Result_2
## OUTPUT ##
# | This is | ....a st | ring... |

Надеюсь, это поможет ...

PS:

Я просто понимаю, что забыл результат .... .


$Result_1.Split("|")
## OUTPUT ##
This is
 a string.

 $Result_2.Split("|")
 ## OUTPUT ##
 This is
 ....a st
 ring...

EOF

AxelEri c.

...