![如何 grep 多个其他文件中特定列中一个文件中的所有行?](https://linux22.com/image/151890/%E5%A6%82%E4%BD%95%20grep%20%E5%A4%9A%E4%B8%AA%E5%85%B6%E4%BB%96%E6%96%87%E4%BB%B6%E4%B8%AD%E7%89%B9%E5%AE%9A%E5%88%97%E4%B8%AD%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E8%A1%8C%EF%BC%9F.png)
我有一个文件:combined.txt,如下所示:
GO_GLUTAMINE_FAMILY_AMINO_ACID_METABOLIC_PROCESS
REACTOME_APC_CDC20_MEDIATED_DEGRADATION_OF_NEK2A
LEE_METASTASIS_AND_RNA_PROCESSING_UP
RB_DN.V1_UP
REACTOME_ABORTIVE_ELONGATION_OF_HIV1_TRANSCRIPT_IN_THE_ABSENCE_OF_TAT
...
在我当前的目录中,我有多个 .xls 文件,这些文件的命名类似于合并的.txt 中的行,例如: GO_GLUTAMINE_FAMILY_AMINO_ACID_METABOLIC_PROCESS.xls
在这些 .xls 文件中,我想检索名为“GENE_TITLE”的列中的所有内容,在名为“METRIC SCORE”的列中我有“是”
这些文件看起来像:
NAME PROBE GENE SYMBOL GENE_TITLE RANK IN GENE LIST RANK METRIC SCORE RUNNING ES CORE ENRICHMENT
row_0 MKI67 null null 51 3.389514923095703 0.06758767 Yes
row_1 CDCA8 null null 96 2.8250465393066406 0.123790346 Yes
row_2 NUSAP1 null null 118 2.7029471397399902 0.17939204 Yes
row_3 H2AFX null null 191 2.3259851932525635 0.22256653 Yes
row_4 DLGAP5 null null 193 2.324765920639038 0.2718671 Yes
row_5 SMC2 null null 229 2.2023487091064453 0.31562105 No
row_6 CKS1B null null 279 2.0804455280303955 0.3555722 No
row_7 UBE2C null null 403 1.816525936126709 0.38350475 No
在输出文件中,我将在每一行中添加:
GO_GLUTAMINE_FAMILY_AMINO_ACID_METABOLIC_PROCESS 51 96 118 191 193
<name of the particular line in combined.txt> <list of all entries in GENE_TITLE which have METRIC SCORE=Yes>
到目前为止我尝试过的是:
grep -iw -f combined.txt *.xls > out1
我也尝试过这个,但在这里我没有使用combined.txt中的信息,也没有获取标有“是”的值,只是从所有文件中提取第五列
awk '{ a[FNR] = (a[FNR] ? a[FNR] FS : "") $5 } END { for(i=1;i<=FNR;i++) print a[i] }' $(ls -1v *.xls) > out2
这可能有点接近,但仍然不存在:
awk 'BEGIN {ORS=" "} BEGINFILE{print FILENAME} {print $5 " " $8} ENDFILE{ printf("\n")}' *.xls > out3
我得到类似的东西:
GENE_TITLE GENE 1 Yes 4 Yes 11 Yes 23 Yes 49 Yes 76 Yes 85 Yes 118 No 161 No....
GENE_TITLE GENE 0 Yes 16 No 28 Yes 51 Yes 63 No 96 Yes 182 Yes 191 Yes
...
所以我想要的输出将具有而不是“GENE_TITLE GENE”,它确实从其中获取这些值的文件名(不带.xls后缀):0是16否28是51是63否96...不包括其中的那个没有”
更新
我确实得到了我需要的文件,但我编写了尽可能丑陋的代码(见下文)。如果有人有更优雅的东西,请分享。
这就是我得到它的方式:
awk '{print FILENAME " "$5 " "$8}' *.xls | awk '!/^ranked/' | awk '!/^gsea/'| awk '!/^gene/' | awk '$3!="No" {print $1 " " $2}' | awk '$2!="GENE_TITLE" {print}' |awk -v ncr=4 '{$1=substr($1,0,length($1)-ncr)}1' | awk -F' ' -v OFS=' ' '{x=$1;$1="";a[x]=a[x]$0}END{for(x in a)print x,a[x]}'>out3
grep -iw -f combined.txt out3 > ENTR_combined_SET.txt
答案1
xargs -I {} awk '$8 == "Yes" { title = title OFS $5 } END { print substr(FILENAME,1,length(FILENAME)-4), title }' {}.xls <combined.txt
这用于为文件中列出的每个名称xargs
执行一个程序。awk
combined.txt
程序awk
会获得从文件中读取的任何名称,combined.txt
并将.xls
其添加到名称末尾作为其输入文件。
该awk
程序从第 5 列收集第 8 列为 的每一行的数据Yes
。然后将该字符串与文件名一起打印,并截去最后四个字符(文件名后缀)。
答案2
重击脚本:
#!/bin/bash
# read combined.txt line by line
while read -r line; do
# skip missing file ${line}.xls
[ ! -f "$line".xls ] && continue
# echo line and one space character (without newline)
echo -n "$line " >> out
# get 5th column if line ends with "Yes" and optional whitespace at end of line
# replace newline '\n' with space ' '
sed -nE 's/^\S+\s+\S+\s+\S+\s+\S+\s+(\S+).*\sYes\s*$/\1/p' "$line".xls | tr '\n' ' ' >> out
# add newline
echo >> out
done < combined.txt
一行:
while read -r line; do [ ! -f "$line".xls ] && continue; echo -n "$line " >> out; sed -nE 's/^\S+\s+\S+\s+\S+\s+\S+\s+(\S+).*\sYes\s*$/\1/p' "$line".xls | tr '\n' ' ' >> out; echo >> out; done < combined.txt
请注意,中的每一行在out
行尾都会有一个额外的空格字符。