我有这一行,制表符分隔:
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可以轻松做到的事情......任何人都有解决方案吗?
感谢。
答案 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。