2017-08-24 51 views
-1

我有以下两个文件(实际数据是制表符分隔的代替分号): input.txtAWK匹配子串从2档

Astring|2042;MAR0303;foo1;B 
Dstring|2929;MAR0283;foo2;C 

db.txt更新

TG9284;Astring|2042|morefoohere_foo_foo 
TG9281;Cstring|2742|foofoofoofoofoo Dstring|2929|foofoofoo 

因此,input.txt的第1列是db.txt的第2列的子字符串。这里只有两个由“|”隔开的“字段”。

我想用awk来匹配这些两列(在制表符分隔的形式再次)打印以下:

Astring|2042;MAR0303;foo1;B;TG9284 
Dstring|2929;MAR0283;foo2;C;TG9281 

这是我的代码:

awk -F'[\t]' 'NR==FNR{a[$1]=$1}$1 in a {print $0"\t"$1}' input.txt db.txt 

编辑 第2栏的db.txt包含由空格分隔的第1列input.txt的字符串。真实例子中的字符串比摘录中显示的要多得多。

+0

并且'db.txt'确实有一个管道后面的''2'',而不是分号? –

+0

是的。该文件有两列,第二列有一种由一些字符串 - 管道 - 4位数字组成的标识符。该部分应该匹配。 – rororo

+0

@anubhava我想要'TG ####' – rororo

回答

2

您可以使用此awk

awk 'BEGIN{FS=OFS="\t"} NR==FNR{ 
    split($2, b, "|"); a[b[1] "|" b[2]]=$1; next} 
$1 in a {print $0, a[$1]}' db.txt input.txt 

Astring|2042 MAR0303 foo1 B TG9284 
Dstring|2929 MAR0283 foo2 C TG9281 

编辑:

根据您的意见,您可以使用:

awk 'BEGIN{FS=OFS="\t"} NR==FNR { 
    a[$2]=$1; next} {for (i in a) if (index(i, $1)) print $0, a[i]}' db.txt input.txt 

Astring|2042 MAR0303 foo1 B TG9284 
Dstring|2929 MAR0283 foo2 C TG9281 
+0

对不起,我在'db.txt'中犯了一个错误。子字符串可以是_anyhwere_列2 – rororo

+0

好吧,现在检查我编辑的答案。 – anubhava

+0

感谢您的解决方案。为什么你先阅读'db.txt'?我习惯了做相反的... – rororo

0

用分号去,你可以用标签替换:

$ awk -F\; ' 
NR==FNR {      # hash the db file 
    a[$2]=$1 
    next 
} 
{ 
    for(i in a)    # for each record in input file 
     if($1~i) {    # see if $1 matches a key in a 
      print $0 ";" a[i] # output 
      # delete a[i]  # delete entry from a for speed (if possible?) 
      break    # on match, break from for loop for speed 
     } 
}' db input     # order order 
Astring|2042;MAR0303;foo1;B;TG9284 
Dstring|2929;MAR0283;foo2;C;TG9281 

对于每个记录在input脚本匹配$ 1票反对的db每个条目,所以它的速度慢。您可以通过在ifdelete之间添加break并将其与a(如果您的数据允许)相匹配的条目加快速度。

0

能否请您尝试以下,让我知道这是否对你有帮助。它将查找从input.txt到db.txt文件的$ 1的完全匹配。

awk -F";" 'FNR==NR{a[$1]=$0;next} {for(i in a){match($0,i);if(substr($0,RSTART,RLENGTH)){print a[i]";"$1}}}' input.txt db.txt