如何从awk或sed的行中提取单引号中的数字?

时间:2014-02-26 19:54:27

标签: regex bash sed awk

我有这一行,制表符分隔:

chr1    11460   11462   '16/38' 421     +       chr1    11460   11462   '21/29' 724     +       2
chr1    11479   11481   '11/29' 379     +       chr1    11479   11481   '20/5' 667     +       2

我想要做的是测试''中的所有第二个数字是否大于或等于10.如果是,我将输出这一行。所以结果应该是打印第一行

chr1    11460   11462   '16/38' 421     +       chr1    11460   11462   '21/29' 724     +       2

我可以编写一个perl代码来执行此操作。但这似乎是awk可以轻松做到的事情......任何人都有解决方案吗?

感谢。

4 个答案:

答案 0 :(得分:3)

如果设置了正确的字段分隔符,则非常简单:

awk -F "['/]" '{for (i=3; i<=NF; i+=3) if ($i<10) next; print}' file

答案 1 :(得分:1)

获取单引号内容的最简单方法可能只是从每行的两端去除所有内容,包括单引号:

$ sed "s/^[^']*'//;s/'.*//" file
16/38
11/29

这个sed表达式包含两个命令:

  • s/^[^']*'// - 将所有文字剥离到第一个单引号,
  • s/'.*// - 剥离第一个(剩余)单引号中的所有文本到EOL。

要将此包装在一个shell脚本中,使用该数据执行某些操作需要..好吧,一个shell脚本......

您可以使用bash的read命令解析这些内容。例如:

#!/bin/bash
IFS=/
sed "s/^[^']*'//;s/'.*//" file \
| while read left right; do
  echo "$left / $right"
done

要实现抓取多个单引号数字内容的内容,可以适当扩展sed脚本,并根据需要实现if语句。例如,用于获取两个单引号字符串的sed表达式可能是:

sed "s/^[^']*'\([^']*\)'[^']*'\([^']*\)'.*/\1 \2/"

这是一个使用两组括号\(\)的大型正则表达式,用于标记将放置在输出\1\2中的模式。

但根据列位置解析事情可能会更好:

$ while read _ _ _ A _ _ _ _ _ B _; do echo "$A .. $B"; done < file
'16/38' .. '21/29'
'11/29' .. '20/5'

实际上,实现您的编程逻辑是留给读者的练习。如果您希望我们帮助您完成脚本,请包含您目前的工作。

答案 2 :(得分:1)

只要这些是字符串中唯一的'字符且数字不会有前导零,您就可以使用正则表达式:

\d\d+'.*\d\d+'

如果其中任何一个先决条件不成立,则可以进行更改,但这取决于具体情况。

您应该能够使用grep来获取使用该正则表达式所需的行。 以下仅将第一行放到stdout:

grep \d\d+'.*\d\d+' "chr1    11460   11462   '16/38' 421     +       chr1    11460   11462   '21/29' 724     +       2
chr1    11479   11481   '11/29' 379     +       chr1    11479   11481   '20/5' 667     +       2"

答案 3 :(得分:1)

我的版本,严重矫枉过正,但每行应该使用任何数量的'xx / xx':

awk -F'\t' "{
    found=1;
    for(i=0;i<NF;i++){
        if(match(\$i, /'[[:digit:]]+\/([[:digit:]]+)'/, capts)){
            if(capts[1] < 10){
                found=0;
                break;
            }
        }
    }
    if(found){
        print;
    }
}" file.txt

<强>解释

这将循环遍历该行的每个字段并对该字段应用正则表达式以查找“xx / xx”的最后几位。如果最后的数字小于10,它将跳出循环并转到下一行。如果所有字段都由if循环处理,并且最后一个数字小于10,则会打印该行。

注意:

看到我正在使用匹配函数来捕获正则表达式组,这只适用于GNU awk。