使用 sed 从变量中删除多个正则表达式

使用 sed 从变量中删除多个正则表达式

我确信这很简单,但我似乎找不到一个很好的例子。我正在尝试解析 /proc/1/exe 以找到盒子的初始化系统。 Exe 是一个指向 init 系统的符号链接,但是当您统计该文件时,它里面有引号,我想删除它。不幸的是,我在exe中看到了常规撇号(U+0027)以及左右单引号(U+2018和U+2019)。它因系统而异。我不确定这是否是由于我正在运行的 shell 和/或其版本所致,是否是 stat 实用程序所致,或者是否是系统本身所致,我刚刚看到了所有这三个字符(有时混合在一起)。

最终,我只想使用相同的 sed 命令删除所有这些字符。到目前为止,我只能通过将 sed 管道传输到另一个 sed 命令来完成此操作。

这是整个exe文件:

$stat /proc/1/exe

  File: '/proc/1/exe' -> '/sbin/init'
  Size: 0           Blocks: 0          IO Block: 1024   symbolic link
Device: b9h/185d    Inode: 76948360    Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-02-01 14:52:39.101744022 -0700
Modify: 2017-01-25 12:52:20.741244423 -0700
Change: 2017-01-25 12:52:20.741244423 -0700
 Birth: -

请注意,在这个示例中,它只是常规的撇号,但我也看到了其他引号字符。所以我首先获取我需要的内容:

$stat /proc/1/exe | grep File: | awk -F '->' '{print $2}'
'/sbin/init'

现在我想删除引号,而能够删除所有不同类型引号的唯一方法是使用多个 sed 命令:

$stat /proc/1/exe | grep File: | awk -F '->' '{print $2}' | sed 's/\xe2\x80\x98//g' | sed 's/\xe2\x80\x99//g' | sed 's/\x27//g'
 /sbin/init

之后我将其通过管道传输到另一个 awk 语句:

$stat /proc/1/exe | grep File: | awk -F '->' '{print $2}' | sed s'/\xe2\x80\x98//g' | sed 's/\xe2\x80\x99//g' | sed 's/\x27//g' | awk -F '/' '{print $NF}'
init

我知道 /proc/1/comm 或只是在 /proc/1/exe 上使用 ls 。问题是如何将三个 sed 命令合并为一个。它应该是:

如果存在左引号、右引号或撇号,请将其删除。它应该在所有情况下都这样做。

顺便说一句,如果有人知道更好的命令来获取盒子的初始化系统(除了 /proc/1/comm ,因为我发现它不可靠)或者可以使这些命令更有效,我会很感兴趣在学习它的过程中。

答案1

正如其他人所指出的,有多种更好的方法来确定 PID 1 的性质。在单个管道中使用多次调用grep,sed和几乎从来都不是一个好主意。awk如果grep做不到,请使用sed.如果sed无法(轻松)做到这一点,请使用awk.因此:

stat /proc/1/exe | sed -n '/File:/{s/.*-> *[\xe2\x80\x98]//;s/[\xe2\x80\x99].*//p;q}'

答案2

这里可以采取稍微不同的方法,它仍然满足最初的问题“如何将三个 sed 命令组合成一个”,并且还改进了命令本身。毫无疑问,还有很多其他方法可以解决如何检索 init 系统的次要问题。

您无需尝试删除不需要的内容,而是可以使用捕获组捕获所需的内容,并且可以使用字符集匹配多个值。字符集由括号“[]”表示。在里面你准确地输入你想要匹配的内容,你会在它们之间得到一个隐式的 OR 语句。所以为了匹配左引号或者您使用的撇号:

[\xe2\x80\x98 \x27]

左引号是“e28098”十六进制字符,撇号是“27”十六进制字符。我在它们之间放置一个空格只是为了强调两个单独的字符,但从技术上讲,这将匹配左引号或者空间或者撇号。如果您不想匹配,请将空格删除。如果您想匹配正确的报价,您也可以添加“e28099”。

要改进命令本身并仅拉取“init”或“systemd”,您可以使用捕获组采取不同的方法。捕获组由括号“( )”表示。然后您可以引用该捕获组。例如,我最终使用此命令来捕获我所需要的内容:

stat /proc/1/exe | sed -rn 's/^.*File:.*->.*[\xe2\x80\x98\x27]\/.*\/(.+)[\xe2\x80\x99\x27]$/\1/p'

捕获组(括号之间的“.+”)捕获左引号或撇号与右引号或撇号之间的最后一个正斜杠之后的任何内容。它是通过使用“\1”引用的(因为它是第一个也是唯一的捕获组)。 Sed 将整行替换为捕获组中的内容。

  • -r 用于扩展正则表达式(至少在我的 sed 版本上)
  • -n 用于抑制打印。当与“/p”选项结合使用时,它只会打印与模式匹配的行,但在它们被替换之后。这使得 sed 的操作就像 grep 一样。

希望这对其他人有帮助。

相关内容