因此,我拥有所有这些用户登录信息(service、admin、J009878),您在此处看到的此表来自另一个命令,其输出就是我保存在 file.txt 中的此表。我想要实现的是浏览 file.txt 文件(该表所在的位置)并能够提取与登录信息匹配的 ID。登录信息(可以是 J009878、admin 或其中任何一个)以变量 $user 的形式出现,然后必须使用该变量来提取与该变量匹配的 id。
例如,如果我的变量用户获得登录名或 ID J665454,那么我希望能够从那里提取 23 的 ID。同样,如果收到 admin 的登录名,则需要提取 id 4 并将其保存在变量中。
任何帮助将不胜感激。谢谢你!
答案1
您可以使用以下 GNU sed 命令来实现此目的,假设$person
存储了他们的登录名。
sed -En "s_\s*\|([0-9]+)\s*\|\s*$person\s*\|.+_\1_p"
例子:
❯ set person Jack
❯ cat table.txt | sed -En "s_\s*\|([0-9]+)\s*\|\s*$person\s*\|.+_\1_p"
4
❯ set person David
❯ sed -En "s_\s*\|([0-9]+)\s*\|\s*$person\s*\|.+_\1_p" table.txt # also works
32
解释:
sed -E -n
:-E 设置扩展正则表达式标志,-n 使 sed 不打印,除非明确告知这样做。
s_<regex>_<replacement>_p
:s
是替代命令(可以_
是任何字符,我_
为了可读性而选择)。它匹配正则表达式,并将其替换为替换项。最后的p
使其打印,并且由于我们使用了-n
,它最终只会打印匹配的行。
\s*\|([0-9]+)\s*\|\s*$person\s*\|.+
:表达式的正则表达式部分,解释如下
正则表达式 | 意义 |
---|---|
\s*\| |
这匹配任意数量的空格(以防表以空格开头),然后匹配文字| 。我们逃避了,| 因为| 在正则表达式中具有特殊含义。 |
([0-9]+) |
这匹配 0-9 范围内的一个或多个字符。在大多数正则表达式引擎中,您也可以使用\d 此功能,但sed 不支持\d .该表达式周围的括号将其放入一个“组”中,我们可以在替换中使用 来引用它\1-9 。例如,echo "hello" | sed "s_([aeiou])/\1\1_g" 会产生heelloo , 因为每个元音都被替换为它自己的 2 个副本(g 标志使其每行工作多次) |
\s*\|\s* |
任意数量的空间(包括无空间),然后是文字| ,然后是任意数量的空间(包括无空间)。 |
$person |
这部分将被您的 shell 替换,并且 sed 永远不会看到,因此这最终会匹配调用脚本时的字母Jack 或任何内容。$person |
\s*\| |
任意数量的空间(包括无空间),然后是文字| .我们必须匹配这些,以确保Jackie 当我们正在寻找的登录名是 时也不会匹配Jack 。 |
.+ |
这可以匹配任何内容,直到该行的末尾。这很重要,因为当我们进行替换时,任何未匹配的内容最终仍将被打印,因此我们需要确保匹配整行。 |
\1
:我们将正则表达式匹配的任何内容(希望是整行)替换为组 1,即我们要查找的 ID 号。这最终使整行仅保留该 ID 号,因此我们打印该行。