我有这行,制表符分隔:
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可以轻松做到的。。有人有解决方案吗?
谢谢。
如果你设置了正确的字段分隔符,这很容易:
awk -F "['/]" '{for (i=3; i<=NF; i+=3) if ($i<10) next; print}' file
获取单引号内内容的最简单方法可能只是剥去每行两端的所有内容,直到并包括单引号:
$ 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'
实际上,实现编程逻辑是留给读者的练习。如果你想让我们帮你写剧本,请把你到目前为止的作品包括在内。
只要这些是字符串中唯一的'字符,并且数字没有前导零,就可以使用正则表达式:
dd+'.*dd+'
如果这两个先决条件中的任何一个都不成立,可以做出改变,但这将取决于情况。
您应该能够使用grep来获得使用该regex所需的行。以下仅将第一行放入stdout:
grep dd+'.*dd+' "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"
我的版本,严重高估,但每行应该使用任何数量的"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,则它将打印该行。
注意:
鉴于我正在使用match函数来捕获regex组,这将仅适用于GNU awk。