Tuesday, April 26, 2022

[SOLVED] Bash to Grep and Exclude At the Same Time Using Regex

Issue

I want to grep a string from command output but remove a substring at the same time. For instance

String = Active: active (running) since Sat 2022-03-12 20:02:20 PKT; 1h 31min ago

What I want = active (running) since 20:02:20 PKT

Removed

  1. Active:
  2. Sat 2022-03-12
  3. ; 1h 31min ago

To do that I have been using regular expression initially

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

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

Can you tell how can i ignore date as well as last semi-colon ; while keeping the time only and have output exactly like:

active (running) since 01:06:43 PKT

Thanks

Full output of command:

● 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```

Solution

You can use

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

Details:

  • -nE - n suppresses default line output and E enables the POSIX ERE regex syntax
  • ^Active: +(.* since ).*([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*).* - finds lines matching
    • ^ *Active: + - start of string, zero or more spaces, Active: and one or more spaces
    • (.* since ) - Group 1 (\1): any text and then space + since + space
    • .* - any text
    • ([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*) - two digits, :, two digits, :, two digits, and then any zero or more chars other than ;
    • .* - the rest of the string
  • \1\2 - concatenated Group 1 and 2 values
  • p - prints the result of the substitution.

See the online demo:

#!/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"

Output:

active (running) since 20:02:20 PKT


Answered By - Wiktor Stribiżew
Answer Checked By - David Marino (WPSolving Volunteer)