Фильтровать только заглавные слова из файла - PullRequest
0 голосов
/ 04 октября 2018

У меня есть файл output.txt, содержащий около 1000 слов, который выглядит следующим образом:

SESSIONDAYOFWEEK
FILMTITLELONGALT
tblTrans_Ticket.
ADMITDETAILSALT2
MESSAGESTUB2ALT3
StartDayOfWeek
Description
MESSAGESTUB2ALT2
FILMTITLESHORTALT
Applications
TICKETTYPELONGALT

Мне нужно отфильтровать этот файл, выбрать только слова, содержащие только символы UPPER CASE, и избавиться от них.те, которые имеют символы нижнего регистра.

Я запускаю эту команду в PowerShell:

Get-Content .\out.txt | ForEach-Object if ($_.IsUpper) {Write-Host $_}

, и оболочка анализирует все слова одно за другим, и для каждого слова печатает меня:

ForEach-Object : Input name "if" cannot be resolved to a method.
At line:1 char:25
+ ... et-Content .\out.txt | ForEach-Object if ($_.IsUpper) {Write-Host $_}
+                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (TAIL:PSObject) [ForEach-Object], PSArgumentException
    + FullyQualifiedErrorId : MethodNotFound,Microsoft.PowerShell.Commands.ForEachObjectCommand

Я не понимаю, где я не прав?

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

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

Get-Content .\out.txt | Where-Object { $_ -cmatch "\b[A-Z0-9_]+\b" }

Where-Object действует как фильтр, пропуская все, что совпадает, и отбрасывая все, что не соответствует.

-cmatch выполнит регистрозависимое совпадение с учетом регистра

Объяснение регулярного выражения:

+ Квантор - соответствует от одного до неограниченного количества раз, сколько возможно,возвращая при необходимости (жадный)

A-Z один символ в диапазоне от A (индекс 65) до Z (index 90)

0-9 один символ в диапазоне между0 (индекс 48) и 9 (индекс 57)

_ соответствует символу _ буквально

\b для подтверждения позиции на границе слова

Вы можетеудалите 0-9 и _, если вы не хотите пропустить слова с этими символами через фильтр.

См .: https://regex101.com/r/CfgEmU/1

0 голосов
/ 05 октября 2018

howdy Francesco Mantovani,

, как уже упоминали другие, тип [string] НЕ имеет свойства .IsUpper.тип [char] имеет метод .IsUpper() , но ему также не хватает свойства с таким именем.[ ухмылка ]

вы можете проверить все элементы массива в верхнем регистре, таким образом ...

$Collection.Where({$_ -ceq $_.ToUpper()})

надеюсь, что это поможет,
ли

0 голосов
/ 04 октября 2018

Используйте оператор -cmatch для регистрозависимого сопоставления с регулярным выражением ( регулярное выражение ):

Get-Content .\out.txt | Where-Object { $_ -cmatch  '^\p{Lu}+$' }
  • -cmatch - регистрчувствительный вариант оператора -match (псевдоним которого -imatch);учитывая, что -match не чувствителен к регистру, -cmatch должен использоваться для обнаружения различий в регистре.

  • \p{Lu} соответствует одному символу в верхнем регистре - включая символы без ASCII с ударениемнапример, Ü [1] - и добавление + соответствует одному или нескольким подряд.Заключение выражения в ^ (начало строки) и $ (конец строки) означает, что сопоставляются только строки, полностью состоящие из заглавных букв.

    • Ansgar Wiechers предлагает -cnotmatch '\p{Ll}' вместо этого, что работает немного по-другому: это исключило бы строки, содержащие хотя бы один строчный символ, что означает, что строки сохраняются, даже если они (также) содержат небуквенные символы (до тех пор, покапоскольку здесь нет строчных букв).

Альтернатива с Select-String, которая может работать лучше:

Select-String -CaseSensitive '^\p{Lu}+$' .\out.txt | Select-Object -ExpandProperty Line

Select-String также не чувствительна к региструпо умолчанию (как и PowerShell в целом), поэтому здесь требуется переключатель
-CaseSensitive.

Обратите внимание, что, несмотря на свое название, Select-String начиная с PowerShell Core 6.1.0 не поддерживаетвывод согласованных линий напрямую;вместо этого он выводит объекты информации о совпадении, свойство .Line которых содержит совпавшую строку, поэтому необходимо Select-Object -ExpandProperty Line.
В этом выпуске GitHub предлагается добавить новый параметр переключателя для поддержки прямого выводасоответствующие строки.


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

Код, выполняемый командлетом ForEach-Object, должен быть передан как сценарий block - т. е. фрагмент кода, заключенный в { ... }.

. Вы пренебрегли этим, что вызвало синтаксическую ошибку, которую вы видели.

Кроме того, тип [string](строка .NET) не имеет метода .IsUpper() (и даже если он есть, вы забыли () после .IsUpper).

Только тип [char] имеет .IsUpper()метод, а именно static , который вы можете вызвать следующим образом: [char]::IsUpper('A') - но вам придется вызывать этот метод в цикле для каждого символа в вашей входной строке:

Get-Content .\out.txt | Where-Object { 
  foreach ($c in $_.ToCharArray()) { if (-not [char]::IsUpper($c)) { return $False } }
  $True
}

Наконец, не используйте Write-Host для возврата результатов - Write-Host распечатки только на консоли - yВы не сможете перехватить или перенаправить такой вывод [2] .Вместо этого используйте Write-Output или, что еще лучше, полагайтесь на неявное поведение PowerShell: простое использование $_ в качестве собственного оператора выведет его - любое выражение или команда, которую вы не захватываете и не перенаправляете, автоматическиoutput (отправляется в поток вывода об успешном завершении).


[1] Напротив, при использовании выражения диапазона символов [A-Z] распознаются только символы верхнего регистра ASCII (английский).

[2] Никогда в PSv4-, но с дополнительными усилиями вы можете в PSv5 + - но дело в том, что Write-Host не предназначен для вывода результатов (данных).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...