从命令输出中提取子字符串

从命令输出中提取子字符串

如何从下面的命令输出中仅提取kimtin和子字符串。tintu子字符串不能通过简单地拆分来获得-。这些xxx位是特定运算符的字符串,所以我将它们散列出来。

> kubectl get pods
xxxxxxxxxxxxxxx-x-ram-kdm-xxxxx-ramkim-6b4c49f589-6hqcj       
xxxxxxxxxxxxxxx-x-ram-kdm-xxxxx-ramtin-8d49b4dc7-bmvck        
xxxxxxxxxxxxxxx-x-ram-kdm-xxxxx-ramtintu-69b8c5b689-64fxw 

抱歉,由于客户限制,我无法添加太多信息。我将描述输出的性质。 ram 是固定名称,与需要提取的字符串连接。每个输出行中的 - 数量不固定,字母数量也不固定。在此示例中 ram 显示为 -ram- 。我只需要提取与 ram+'extract-string' 连接的字符串,无论它出现在哪里,但它只出现一次。

答案1

根据您的评论进行更新,我认为这会满足您的要求:

$ awk -F- '{
    for (i=1;i<=NF;i++) {
      if ($i ~ "^ram.+") { sub("^ram","",$i); print $i} }
    }' kubectl.txt
kim
tin
tintu

英文:对于每个输入行的每个字段,如果字段值与正则表达式匹配^ram.+(以“ram”开头,后跟最后一个更多字符)然后使用 sub() 从字段开头删除“ram”并打印该字段。

或者在 Perl 中:

$ perl -F- -lne 'foreach (@F) { print $1 if (m/^ram(.+)/) }' kubectl.txt 
kim
tin
tintu

英语:对于每行的每个字段,如果该字段与正则表达式“^ram(.+)”匹配,则打印与(.+)子表达式匹配的字段的捕获部分(即“^ram”之后的所有内容)。

注意:如果一行中有多个字段与该模式匹配,那么它们都会被打印。如果您只想要第一个这样的字段,请使用next停止处理当前行并跳到下一行:

awk -F- '{
    for (i=1;i<=NF;i++) {
      if ($i ~ "^ram.+") { sub("^ram","",$i); print $i; next } }
    }' kubectl.txt

或者

perl -F- -lne 'foreach (@F) { if (m/^ram(.+)/) { print $1; next } }' kubectl.txt

我将在下面留下我的旧答案,因为它们可能对其他有类似问题的读者仍然有用:

我不确定你到底想要什么输出,所以这里有一些可能性。它们都只为字段 6 ( $6) 以字段 3 ( ) 的内容开头的行生成输出"^" $3。所有其他行都将被忽略。

kubectl.txt是一个包含示例输出的文本文件kubectl get pods

字段 6 的子字符串,从字符 4 到字段末尾:

$ awk -F- '$6 ~ "^" $3 { print substr($6,4) }' kubectl.txt 
kim
tin
tintu

使用 删除字段 6 并从开头删除字段 3 的内容sub()。与上面的示例不同,这不是硬编码来去除前 3 个字符,因此适用于任何长度的 $3。

$ awk -F- '$6 ~ "^" $3 { sub("^" $3,"",$6); print $6}' kubectl.txt 
kim
tin
tintu

与上面的字段 7 和 8 相同,用空格分隔:

$ awk -F- '$6 ~ "^" $3 { sub("^" $3,"",$6); print $6, $7, $8}' kubectl.txt
kim 6b4c49f589 6hqcj
tin 8d49b4dc7 bmvck
tintu 69b8c5b689 64fxw

与上面相同,但带有-分隔符。

$ awk -F- -vOFS=- '$6 ~ "^" $3 { sub("^" $3,"",$6); print $6, $7, $8}' kubectl.txt 
kim-6b4c49f589-6hqcj
tin-8d49b4dc7-bmvck
tintu-69b8c5b689-64fxw

答案2

这将对任何行长度执行此操作,前提是您始终希望该单词出现在行中最后一个“ram”之后:

sed 's/.*ram\(\w\+\).*/\1/' your_file

其工作方式如下:

  • 我搜索所有内容,直到最后一次出现“ram”.*ram
  • \(我记得上面使用和之间的东西\)
  • 在这种情况下,这将是一个或多个单词字符\w\+
  • 匹配该行的其余部分.*
  • 然后替换成记住的内容\1

一旦您确认它执行了您想要的操作,-i如果您想直接更改文件,只需添加:

sed -i 's/.*ram\(\w\+\).*/\1/' your_file

需要明确的是,上面的内容将变成:

xxxxxxxxxxxxxxx-x-ram-kdm-xxxxx-ramkim-6b4c49f589-6hqcj       
xxxxxxxxxxxxxxx-x-ram-kdm-xxxxx-ramtin-8d49b4dc7-bmvck        
xxxxxxxxxxxxxxx-x-ram-kdm-xxxxx-ramtintu-69b8c5b689-64fxw

进入这个:

kim
tin
tintu

答案3

如果您想要获取的只是帖子中示例中的kim,tin和字符串,您可以使用以下命令来完成:tintu

cut -c 36- | sed "s/-.*//"

这里有几个例子:

echo "xxxxxxxxxxxxxxx-x-ram-kdm-xxxxx-ramtintu-69b8c5b689-64fxw" |  cut -c 36- | sed "s/-.*//"

输出:tintu

对于包含您帖子中的输入的文件:

cat file |  cut -c 36- | sed "s/-.*//"

输出:

kim
tin
tintu

这可能是显而易见的,但只有当字符串36在所需字符串之前始终有字符时,这才有效。

答案4

无论下面命令的哪一列都将提供输出

awk -F "-" '{for(i=1;i<=NF;i++){if($i ~ /kim|tin|tintu/){print substr($i,4)}}}' filename

输出

kim
tin
tintu

相关内容