Bash 使用正则表达式同时进行 Grep 和排除

Bash to Grep and Exclude At the Same Time Using Regex

我想从命令输出中 grep 一个字符串,但同时删除一个子字符串。例如

String = 活动:活动 (运行) 自星期六 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```

你可以使用

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

详情:

  • -nE - n 抑制默认行输出并且 E 启用 POSIX ERE 正则表达式语法
  • ^Active: +(.* since ).*([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*).* - 查找匹配的行
    • ^ *Active: + - 字符串的开头,零个或多个 spaces,Active: 和一个或多个 spaces
    • (.* since ) - 第 1 组 (</code>):任意文本,然后是 space + <code>since + space
    • .* - 任何文本
    • ([0-9]{2}:[0-9]{2}:[0-9]{2}[^;]*) - 两位数,:,两位数,:,两位数,然后是 ;[=53= 以外的任何零个或多个字符]
    • .* - 字符串的其余部分
  • </code> - 连接第 1 组和第 2 组值</li> <li><code>p - p打印替换结果。

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}[^;]*).*//p' <<< "$s"

输出:

active (running) since 20:02:20 PKT

使用您显示的示例,请尝试以下 awk 代码。用 GNU awk 编写和测试。简单的解释是,创建一个名为 val 的 shell 变量并将其值发送到 awk 然后在 awk 程序中我使用 match 函数将正则表达式匹配到获取所需的值。

val="Active: active (running) since Sat 2022-03-12 20:02:20 PKT; 1h 31min ago"
echo "$val"  | 
awk '
match([=10=],/^Active:[[:space:]]+active \(running\)[[:space:]]+.*[0-9]{4}(-[0-9]{2}){2}[[:space:]]+([0-9]{2}:){2}[0-9]{2}[^;]*/){
  val=substr([=10=],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.