【问题标题】:Using regex to match a pattern in the middle of a string with awk, sed, grep ... something linux-y使用正则表达式匹配字符串中间的模式与 awk, sed, grep ... linux-y
【发布时间】:2015-10-03 17:41:57
【问题描述】:

我有一个文件,其中包含 ID 号和一堆代表基因树的模式 例如:

021557  (sfra,(pdep,snud),((spal,sint),(sdro,(hpul,(sprp,afra)))));
005852  (snud,sfra,(pdep,(hpul,((afra,sprp),(sint,(spal,sdro))))));
023685  (sfra,snud,(pdep,(hpul,((sprp,(afra,spal)),(sdro,sint)))));
022020  (sfra,snud,(pdep,(hpul,(afra,(sprp,(sdro,(sint,spal)))))));
028284  (sfra,snud,(pdep,(hpul,(sprp,((sdro,sint),(spal,afra))))));

我对 (spal,afra) 的某个姐妹分类群分组感兴趣。如果树包含 (spal,afra),我想打印另一列的 ID。

如果只在上面的数据上运行,输出应该是: 023685 028284

我打算这样做:

awk '{if ($2 == "(spal,afra)") { print $1 } }'

但我意识到我要匹配的部分是在一堆其他字符中,并且在不可预测的位置......

所以我需要搜索

  1. 任意数量的小写字母或括号或逗号

  2. (spal,afra)

  3. 任意数量的小写字母或括号或逗号或;

另外,我想我想知道其他顺序(afra,spal)的出现。但是如果我没记错的话,我打算运行单独的匹配,组合输出并使用 sort 和 uniq-c 做一些事情......我以后可能会自己弄清楚。

我对此有点陌生,我已经花了几个小时试图弄清楚一些事情。谢谢!

【问题讨论】:

  • [a-z(),]*(\(spal,afra\))[a-z(),;]*
  • ID 是否在字符串中?如果没有,你为什么不能只搜索\(spal,afra\) 作为子字符串而不做任何其他事情?还是类似于 \(spal,[a-z(),]*afra ?哪里有分离?
  • 这是 awk 还是其他命令?我试图弄清楚如何将它作为工作 if 语句的一部分。
  • the file - 你的意思是多行吗?
  • 显示文件中的示例数据以及您的预期输出

标签: regex linux bash awk sed


【解决方案1】:

您似乎将此作为输入文件

$ cat file
021557  (sfra,(pdep,snud),((spal,sint),(sdro,(hpul,(sprp,afra)))));
005852  (snud,sfra,(pdep,(hpul,((afra,sprp),(sint,(spal,sdro))))));
023685  (sfra,snud,(pdep,(hpul,((sprp,(afra,spal)),(sdro,sint)))));
022020  (sfra,snud,(pdep,(hpul,(afra,(sprp,(sdro,(sint,spal)))))));
028284  (sfra,snud,(pdep,(hpul,(sprp,((sdro,sint),(spal,afra))))));

使用 awk

要打印包含(spal,afra) 的任何行的第一列:

$ awk '/[(]spal,afra[)]/{print $1}' file
028284

条件/[(]spal,afra[)]/ 选择包含(spal,afra) 的行,print $1 打印这些行的第一个字段。

在 awk 正则表达式中,括号是活动字符。由于我们要匹配文字括号,我们将它们放在方括号中,例如 [(][)]

使用 sed

$ sed -n '/(spal,afra)/ s/\t.*//p' file
028284

sed -n 不会打印任何东西,除非我们明确要求它这样做。 /(spal,afra)/ 选择包含 (spal,afra) 的行。 s/\t.*//p 删除第一个选项卡之后的所有内容,然后打印剩余的内容。

默认情况下,sed 使用基本的正则表达式。这意味着()处于活动状态。因此,我们不需要逃避它们。

使用 grep 和剪切

$ grep '(spal,afra)' file | cut -f1
028284

grep '(spal,afra)' file 选择包含(spal,afra) 的行,cut -f1 从这些行中选择第一个字段。

与 sed 一样,grep 默认使用基本的正则表达式。这意味着() 都被视为文字字符,无需对其进行转义。

替代方案:寻找(spal,afra)(afra,spal)

如果我们想在(spal,afra)之外寻找(afra,spal),那么我们需要更新正则表达式。以awk为例:

awk '/[(](spal,afra|afra,spal)[)]/{print $1}' file2
023685
028284

这里,竖线| 分隔选项。正则表达式接受栏之前或之后的内容。

【讨论】:

    【解决方案2】:

    您可以在 awk 中使用此非正则表达式搜索:

    awk 'index($0, "(spal,afra)") || index($0, "(afra,spal)") {print $1}' file
    023685
    028284
    

    【讨论】:

      【解决方案3】:

      这应该可以工作(使用扩展正则表达式的 sed):

      sed -nr 's/([^[:space:]]*)[^;]*(\(spal,afra\)|\(afra,spal\)).*/\1/p' file
      

      输出:

      023685
      028284
      

      【讨论】:

        猜你喜欢
        • 2020-11-14
        • 2013-01-23
        • 1970-01-01
        • 2013-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-15
        • 2017-04-13
        相关资源
        最近更新 更多