我想知道是否有更有效的方法来使用awk / grep / sed来解决以下问题?
我想解析输入文件的某一列(在此示例中为第1列),并使用awk / grep /任何其他函数来子集并选择与我的查询匹配的模式。例如,给出以下文件;
chr1 3009844 3009908 DXX 42 -
chr2 3000386 3000450 DXX 15 -
chr3 3000386 3000450 DXX 15 -
chr4 3000386 3000450 DXX 15 -
chr5 3000386 3000450 DXX 15 -
chr6 3000386 3000450 DXX 15 -
chr7 3000386 3000450 DXX 15 -
chr8 3000386 3000450 DXX 15 -
chr9 3000386 3000450 DXX 15 -
chr10 3000386 3000450 DXX 15 -
chr11 3000386 3000450 DXX 15 -
chr12 3000386 3000450 DXX 15 -
chr13 3000386 3000450 DXX 15 -
chr14 3000386 3000450 DXX 15 -
chr15 3000386 3000450 DXX 15 -
chr16 3000386 3000450 DXX 15 -
chr17 3000386 3000450 DXX 15 -
chr18 3000386 3000450 DXX 15 -
chr19 3000386 3000450 DXX 15 -
chrX 3000386 3000450 DXX 15 -
chrY 3000386 3000450 DXX 15 -
chr1_GL456210_random 3000386 3000450 DXX 15 -
chr1_GL456211_random 3000386 3000450 DXX 15 -
chr1_GL456212_random 3000386 3000450 DXX 15 -
chr1_GL456221_random 3000386 3000450 DXX 15 -
chr4_GL456216_random 3000386 3000450 DXX 15 -
chr4_JH584292_random 3000386 3000450 DXX 15 -
chr4_JH584295_random 3000386 3000450 DXX 15 -
chr5_GL456354_random 3000386 3000450 DXX 15 -
chr5_JH584296_random 3000386 3000450 DXX 15 -
chr5_JH584297_random 3000386 3000450 DXX 15 -
chr5_JH584299_random 3000386 3000450 DXX 15 -
chrX_GL456233_random 3000386 3000450 DXX 15 -
我只想输出第一列中只有chr1-chr22,chrX和chrY的输出,例如;
chr1 3009844 3009908 DXX 42 -
chr2 3000386 3000450 DXX 15 -
chr3 3000386 3000450 DXX 15 -
chr4 3000386 3000450 DXX 15 -
chr5 3000386 3000450 DXX 15 -
chr6 3000386 3000450 DXX 15 -
chr7 3000386 3000450 DXX 15 -
chr8 3000386 3000450 DXX 15 -
chr9 3000386 3000450 DXX 15 -
chr10 3000386 3000450 DXX 15 -
chr11 3000386 3000450 DXX 15 -
chr12 3000386 3000450 DXX 15 -
chr13 3000386 3000450 DXX 15 -
chr14 3000386 3000450 DXX 15 -
chr15 3000386 3000450 DXX 15 -
chr16 3000386 3000450 DXX 15 -
chr17 3000386 3000450 DXX 15 -
chr18 3000386 3000450 DXX 15 -
chr19 3000386 3000450 DXX 15 -
chrX 3000386 3000450 DXX 15 -
chrY 3000386 3000450 DXX 15 -
我设法使用以下命令找到解决方案:
awk '$1 == "chr1" || $1 == "chr2" || $1 == "chr3" || $1 == "chr4" || $1 == "chr5" || $1 == "chr6" || $1 == "chr7" || $1 == "chr8" || $1 == "chr9" || $1 == "chr10" || $1 == "chr11" || $1 == "chr12" || $1 == "chr13" || $1 == "chr14" || $1 == "chr15" || $1 == "chr16" || $1 == "chr17" || $1 == "chr18" || $1 == "chr19" || $1 == "chr20" || $1 == "chrX" || $1 == "chrY"' in_file > out_file
它运作正常,但是想知道亲爱的成员是否会有更优雅的方法来解决问题?或者,如果您可以指向资源来探索linux中的awk / grep,那将非常感激!
答案 0 :(得分:3)
使用正则表达式:
awk '$1 ~ /^chr(1?[0-9]|2[0-2]|X|Y)$/' file
这使用$1 ~ /^pattern$/
来选择完全由pattern
组成的好行(注意^
表示开头,$
表示结尾。)
该模式位于chr(..|..|..)
表单上,表示:匹配chr
后跟|
中()
分隔的条件之一。
这些条件可以是:
1?[0-9]
)2[0-2]
)答案 1 :(得分:2)
如果您想要更容易维护(例如编辑或添加新的行/模式以匹配)以及更容易理解的内容,特别是如果您刚刚开始使用正则表达式,请使用grep -f match.list input.txt
格式:
创建一个包含您要匹配的模式的文件(match.list
):
^chr[1-9][[:space:]]\| # this matches chr1-chr9
^chr1[0-9][[:space:]]\| # this matches chr10-chr19
^chr2[12][[:space:]]\| # this matches chr21-22
^chr[XY][[:space:]]\| # this matches chrX and chrY
new_string_or_pattern\| # ... your new pattern ...
然后就这样打电话给grep
:
grep -f match.list input.txt
正如您在上面所看到的,您甚至可以使用\|
技巧(使用\|
结束每个模式)在模式列表中添加注释,这样您就可以记住您昨天所做的或者在哪里你找到了正则表达式吗?您可以通过添加新行来添加新的固定字符串或模式。此外,如果您发现很难创建复杂的正则表达式,您可能只需创建一个包含您想要匹配的固定字符串的模式文件:
^chrX
^chrY
...
此方法的另一个好处是您可以维护多个模式文件,表示您可能需要每天运行的不同子查询。 E.g。
grep -f chromosomes_n input.txt
grep -f chromosomes_xy input.txt
grep -f chromosomes_random input.txt
该方法的唯一缺点是,如果在每个文件中添加十几个模式,grep
会变慢。但只有当您的输入文件包含数十万行时,这才会成为问题。
答案 2 :(得分:1)
您可以将这个简化的正则表达式与grep
:
grep "^chr\(1\?[0-9]\|2[012]\|[XY]\)[[:space:]]" filename
逻辑包含在括号\(..\)
1\?[0-9]
- 匹配0-9,可选地以1 2[012]
- 匹配2,然后是0,1或2 [XY]
- 匹配X或Y 答案 3 :(得分:0)
根据您发布的示例,您需要获得所需的输出(或其他简单的RE):
awk '$1 !~ /_/' file
awk '$1 ~ /^[[:alnum:]]+$/' file
因此您可能根本不需要列出具体的“模式”,具体取决于您的实际需求。
答案 4 :(得分:-1)
以下将完成工作。
grep -v -w 'random'