Bash для Grep и исключения одновременно с использованием регулярных выражений

Я хочу получить строку из вывода команды, но одновременно удалить подстроку. Например

Строка = Активен: активен (работает) с сб 2022-03-12 20:02:20 PKT; 1ч 31мин назад

Чего я хочу = активен (работает) с 20:02:20 PKT

Удаленный

  1. Активный:
  2. Сб 2022-03-12
  3. ; 1ч 31мин назад

Для этого я изначально использовал регулярное выражение

sudo service sshd status |grep -Po '(?<=Active: )(.*) since (.*);'

active (running) since Mon 2022-03-14 01:06:43 PKT;

Можете ли вы сказать, как я могу игнорировать дату, а также последнюю точку с запятой; сохраняя только время и выводя точно так же, как:

active (running) since 01:06:43 PKT

Спасибо

Полный вывод команды:

● xrdp.service - xrdp daemon
   Loaded: loaded (/lib/systemd/system/xrdp.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2022-03-14 01:06:44 PKT; 3 days ago
     Docs: man:xrdp(8)
           man:xrdp.ini(5)
  Process: 668 ExecStartPre=/bin/sh /usr/share/xrdp/socksetup (code=exited, status=0/SUCCESS)
  Process: 682 ExecStart=/usr/sbin/xrdp $XRDP_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 687 (xrdp)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/xrdp.service
           └─687 /usr/sbin/xrdp

systemd[1]: Starting xrdp daemon...
xrdp[682]: (682)(-1224841088)[DEBUG] Testing if xrdp can listen on 0.0.0.0 port 3389.
xrdp[682]: (682)(-1224841088)[DEBUG] Closed socket 7 (AF_INET6 :: port 3389)
systemd[1]: xrdp.service: Can't open PID file /run/xrdp/xrdp.pid (yet?) after start: No such file or directory```

Вы можете удалить точку с запятой с помощью grep -Po '(?<=Active: )(.*) since (.*)(?=;)', но для даты в середине шаблона вы достигли ограничений GNU grep, поэтому вам придется добавить что-то вроде | sed 's/since [^ ]* [^ ]*/since/' к команде

Fravadona 16.03.2022 20:23
Стоит ли изучать 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
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Ты можешь использовать

sed -nE 's/^ *Active: +(.* since ).*([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*).*/\1\2/p'

Подробности:

  • -nE - n подавляет вывод строки по умолчанию, а E включает синтаксис регулярных выражений POSIX ERE.
  • ^Active: +(.* since ).*([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*).* - находит совпадающие строки
    • ^ *Active: + - начало строки, ноль или более пробелов, Active: и один или более пробелов
    • (.* since ) - Группа 1 (\1): любой текст и затем пробел + since + пробел
    • .* - любой текст
    • ([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*) - две цифры, :, две цифры, :, две цифры, а затем любой ноль или более символов, кроме ;
    • .* - остальная часть строки
  • \1\2 - объединенные значения группы 1 и 2
  • p - pвыводит результат замены.

См. онлайн демо:

#!/bin/bash
s='   Active: active (running) since Sat 2022-03-12 20:02:20 PKT; 1h 31min ago'
sed -nE 's/^ *Active: +(.* since ).*([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*).*/\1\2/p' <<< "$s"

Выход:

active (running) since 20:02:20 PKT

Как ни странно, когда строка хранится в переменной, она дает правильный вывод. При использовании с командой это не работает. sudo service xrdp status | sed -nE 's/^Active: +(.* since ).*([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*).*/\1\2/p' Не выдает вывода, хотя та же строка содержится в многострочном выводе команды. Я добавил полный вывод рассматриваемой команды для справки.

Bilal Bhatti 17.03.2022 07:11

@BilalBhatti Потому что в начале строки есть пробелы. Я добавил ' *' после ^ в регулярном выражении, и теперь это работает.

Wiktor Stribiżew 17.03.2022 09:22

Спасибо. Иногда вывод выглядит так: Как мы можем иметь одно регулярное выражение для обработки обоих?

Bilal Bhatti 17.03.2022 14:12

@BilalBhatti И что тогда? Это ожидается? Что такое вход? Попробуйте sed -nE 's/^ *Active: +(.* since ).*([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*).*|.*(Active: inactive \(dead\)).*/\1\2\3/p'

Wiktor Stribiżew 17.03.2022 14:14

С показанными образцами попробуйте следовать коду awk. Написано и протестировано в GNU awk. Простым объяснением было бы создание переменной оболочки с именем val и отправка ее значения в awk, а затем в программе awk я использую функцию match для сопоставления с регулярным выражением для получения требуемого значения.

val = "Active: active (running) since Sat 2022-03-12 20:02:20 PKT; 1h 31min ago"
echo "$val"  | 
awk '
match($0,/^Active:[[:space:]]+active \(running\)[[:space:]]+.*[0-9]{4}(-[0-9]{2}){2}[[:space:]]+([0-9]{2}:){2}[0-9]{2}[^;]*/){
  val=substr($0,RSTART,RLENGTH)
  sub(/^Active:[[:space:]]+/,"",val)
  sub(/since[[:space:]]+\S+\s+\S+/,"since",val)
  print val
}
'

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

^Active:[[:space:]]+       ##Matching value starting from Active: followed by space(s).
active \(running\)         ##matching active followed by a space followed by (running).
[[:space:]]+.*[0-9]{4}     ##Matching 1 or more spaces then using greedy match to match 4 occurrences of digits.
(-[0-9]{2}){2}             ##Matching - followed by 2 digits and this whole combination 2 times.
[[:space:]]+([0-9]{2}:){2} ##Matching space(s) followed by 2 digits followed by colon and this whole combination 2 times.
[0-9]{2}[^;]*              ##Matching 2 digits and everything after it till a semi-colon comes.

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