Руководство по регулярным выражениям: получение определенного значения из текстового файла с помощью powershell/cmd

Я использую powershell или cmd, чтобы открыть текстовый файл и получить внутри определенное значение или текст.

В настоящее время вывод внутри текстового файла выглядит следующим образом:

Upload Hello.zip: 0 of 933 bytes complete

Upload Hello.zip: 933 of 933 bytes complete
{
  "scanId" : 11260434,
  "scanType" : "Static",
  "analysisStatusType" : "Pending",
  "applicationName" : "Test Application Jenkins",
  "releaseName" : "Release 4",
  "microserviceName" : "",
  "__action__" : "STARTED"
}

Однако я хотел бы получить значение только из идентификатора сканирования.

Это команда, которую я использую:

Select-String -Path C:\Folder\scanjson.txt ':\s*(?<digits>[0-9]+)'

Но он вернет вывод следующим образом:

C:\Folder\scanjson.txt:2:Upload Hello.zip: 0 of 933 bytes complete
C:\Folder\scanjson.txt:4:Upload Hello.zip: 933 of 933 bytes complete
C:\Folder\scanjson.txt:6:  "scanId" : 11260434,

Попробуйте "scanId"\s*:\s*(?<digits>[0-9]+)?

user24714692 25.06.2024 20:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку ваш текстовый файл в основном состоит из JSON, лучше и надежнее удалить преамбулу, отличную от JSON, и использовать ConvertFrom-Json для анализа JSON в объект, к свойствам которого вы можете получить доступ для получения желаемой информации:

# -> 11260434, i.e. a *number*, due to from-JSON parsing.
(
  (Get-Content -Raw C:\Folder\scanjson.txt) -replace '(?s)^.+(?=\{)' |
    ConvertFrom-Json
).scanId
  • Get-Content-Raw считывает файл целиком в одну многострочную строку.

  • -replace '(?s)^.+(?=\{)' удаляет все до первого символа {, исключая его; компоненты регулярного выражения следующие:

    • (?s) — это встроенная опция, которая заставляет . соответствовать символам новой строки.
    • ^ соответствует началу строки.
    • .+ соответствует любой непустой (+) серии символов (.); если ваш входной файл не всегда имеет преамбулу, используйте вместо нее .*.
    • (?=\{) — это предварительное утверждение, которое соответствует символу {, не включая его в сопоставление.
    • Если не указать выражение подстановки, совпадение заменяется пустой строкой, т. е. фактически удаляется.
  • Полученная строка представляет собой действительный JSON, который ConvertFrom-Json анализирует экземпляры [pscustomobject], к свойствам которых, например .scanId, вы можете получить доступ.

    • Обратите внимание, что в отличие от синтаксического анализа регулярных выражений, основанного исключительно на тексте, JSON поддерживает несколько типов данных, в результате чего токен без кавычек, такой как 11260434, анализируется как число.
    • Целое число, как в данном случае, анализируется как тип [int] (System.Int32) в Windows PowerShell, а не как [long] (System.Int64) в PowerShell (Core) 7.

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

Ваше регулярное выражение было слишком либеральным; использовать
"scanId"\s*:\s*(?<digits>[0-9]+) вместо этого;[1] т. е.:

# -> '11260434', i.e. a *string*, due to regex parsing.
(
  Select-String -List -Path C:\Folder\scanjson.txt '"scanId"\s*:\s*(?<digits>[0-9]+)'
).Matches[0].Groups['digits'].Value

Обратите внимание, что необходимо детализировать выходной объект Select-String , который имеет тип [Microsoft.PowerShell.Commands.MatchInfo], чтобы получить интересующее значение группы захвата.

-List гарантирует, что сопоставление прекратится после первого совпадения.

  • Примечание. В случаях, когда вы ожидаете несколько совпадений, вы должны опустить -List и передать вызов ForEach-Object вместо использования прямого доступа к свойству результата (как показано выше):

    Select-String -Path C:\Folder\scanjson.txt '"scanId"\s*:\s*(?<digits>[0-9]+)'| 
      ForEach-Object { $_.Matches[0].Groups['digits'].Value }
    

Из-за использования синтаксического анализа на основе регулярных выражений результатом является строка, просто приведите все выражение к, например [int] чтобы получить номер.


[1] For an explanation of the regex and the option to experiment with it, see this regex101.com page . Note that regex101.com's .NET support is limited to C#, which may require tweaks to PowerShell regexes, such as not using '...' and escaping " chars. as ""; see this answer for guidance.

Спасибо! Основной комментарий/ответ сработал для меня. Что касается того, что я пробовал, я тестировал его на этом сайте: regex101.com/r/IgaNue/1

George 25.06.2024 21:02

Рад это слышать, @Джордж; решение Select-String тоже должно работать, хотя оно возвращает строку (которую можно легко привести к [int]). Напротив, решение ConvertFrom-Json возвращает число (типа [int] в Windows PowerShell и [long] в PowerShell (Core) 7)

mklement0 25.06.2024 21:08

Я использовал это раньше: Select-String -Path C:\Folder\scanjson.txt '"scanId":\s*(?<digits>[0-9]+)' -List | ForEach-Object { $_.Matches[0].Groups['digits'].Value }

George 25.06.2024 21:15

@Джордж: В принципе это работает, но регулярное выражение нарушено; это работает: Select-String -Path C:\Folder\scanjson.txt '"scanId"\s*:\s*(?<digits>[0-9]+)' -List | ForEach-Object { $_.Matches[0].Groups['digits'].Value }. Поскольку ожидается только один результат, мое решение обходится без вызова ForEach-Object.

mklement0 25.06.2024 21:18

@Джордж, повтори ссылку на regex101.com: у тебя были синтаксические ошибки, поскольку сайт требует синтаксиса C#; пожалуйста, см. только что добавленную сноску, в которой есть ссылка с исправленной попыткой и ссылка на ответ, в котором объясняется, как обычно тестировать регулярные выражения PowerShell на regex101.com.

mklement0 25.06.2024 21:34

Плохо, я могу подтвердить, что метод Select-String тоже теперь работает. Я также мог бы попробовать эту команду напрямую, без необходимости сохранять данные в текстовый файл. еще раз спасибо!

George 25.06.2024 21:52

Другие вопросы по теме