【问题标题】:Compare columns in two files and print the match values in specific columns比较两个文件中的列并打印特定列中的匹配值
【发布时间】:2019-02-18 11:05:00
【问题描述】:

在以下情况下。我想找到匹配的值: 文件 1:第 8 列和第 9 列 和 文件 2:第 2 列和第 3 列

如果两个文件中的值完全相同,则像所需的输出文件一样打印

文件1

31429,36689,313212.5,2334362.5,31429,36679,31308,302412.50 2316512.50
31429,36701,313362.5,2334362.5,31429,36681,31311,2334363,31429
31429,36713,313512.5,2334362.5,31429,36719,31358,303312.50 2316512.50
31429,36749,313962.5,2334362.5,31429,36751,31398,2334362,31429
31429,36809,314712.5,2334362.5,31429,36803,31463,2334361,31429
31429,36821,314862.5,2334362.5,31429,36817,31481,2334363,31429

文件2

3000135825 302412.50 2316512.50
3000135837 302562.50 2316512.50
3000135849 302712.50 2316512.50
3000135861 302862.50 2316512.50
3000135873 303012.50 2316512.50
3000135885 303162.50 2316512.50
3000135897 303312.50 2316512.50
3000135909 303462.50 2316512.50
3000135921 303612.50 2316512.50
3000135933 303762.50 2316512.50
3000135945 303912.50 2316512.50

需要的输出

3000135825 302412.50 2316512.50 3667931308 302412.50 2316512.50
3000135897 303312.50 2316512.50 3671931358 303312.50 2316512.50

我试过了 使用这个命令我得到了结果,但是它需要很多时间,因为 file2 有 300 万行并且代码需要太多时间 为了能够使用代码,首先我创建一个名为 tmp1 的临时文件,其中包含来自 file1 的 5、6、8、9 列

awk -F, '{print($5$6,$8,$9)}' file1 > tmp1 

awk 'FNR==NR{a[$2$3]=$0;next}{print $0,a[$2$3]?a[$2$3]:"NA"}' file2 tmp1

【问题讨论】:

  • file1 的长度是多少?如果比 file2 少很多,你可以缓存 file1 的内容。
  • 嗨 karakfa,file1 只有大约 2000 行和 9 列

标签: awk


【解决方案1】:

如果file1的长度远小于file2,你可以缓存file1的内容。

类似的东西(未测试)

$ awk -F, 'NR==FNR      {a[$8,$9]==$6$7; next}   # is $6$7 the key you want to print?
           ($2,$3) in a {print $1,$2,$3,a[$2,$3]}' file1 FS=' ' file2

由于值应该匹配,因此无需再次打印它们。不知道是什么 输出中打印的第四个值,但如果它来自 file1,只需替换它即可。

【讨论】:

  • 嗨 Karakfa,代码不打印输出文件..我们在来自 file1 的输出中打印的值
【解决方案2】:

请您尝试关注一下。

awk 'FNR==NR{a[$8 OFS $9]=$6 $7 OFS $8 OFS $9;next} (($2 OFS $3) in a){print $0,a[$2 OFS $3]}' FS="[, ]"  Input_file1 FS=" " Input_file2

现在添加非单线形式的解决方案。

awk '
FNR==NR{
  a[$8 OFS $9]=$6 $7 OFS $8 OFS $9
  next
}
(($2 OFS $3) in a){
  print $0,a[$2 OFS $3]
}
' FS="[, ]"  Input_file1 FS=" "  Input_file2

解释:现在也为上面的代码添加解释。

awk '
FNR==NR{                              ##Checking condition FNR==NR this will be TRUE when firt Input_file named Input_file1 is being executed.
  a[$8 OFS $9]=$6 $7 OFS $8 OFS $9    ##Creating an array named a whose index is $8 OFS $9 and value if $6 $7 OFS $8 OFS $9.
  next                                ##next keyword is out of the box of awk and will skip further statements from here.
}
(($2 OFS $3) in a){                   ##Statements from here will be executed when 2nd Input_file is being read named Input_file2. Checkingh condition if $2 OFS $3 is present in array a then do following.
  print $0,a[$2 OFS $3]               ##Printing current line along with value of array a whose index is $2 OFS $3.
}                                     ##Closing block for above condition now.
' FS="[, ]" Input_file1 FS=" " Input_file2        ##Setting FS for Input_file1 as comma OR space here then mentioning Input_file1 name then setting FS as space and mentioning Input_file2 name here.

【讨论】:

  • 嗨 RavinderSingh.. 代码完美运行,tks .. 我尝试像这样修改它 awk 'FNR==NR{a[$6 OFS $7]=$6$7;next} (($1)在 a){print $0,a[$1]}' FS="[, ]" file1 FS=" " file2 检查是否在列 file2 中找到第 6 列和第 7 列(file1)中的值。但它不起作用跨度>
【解决方案3】:

为了速度我会考虑:

1 - 尽可能使用shell字符串命令

2 - 仅将必要的列放入文件中

3 - 排序

4 - 将文件和输出存储在变量中 - 打印和文件命令在大循环中花费的时间太长

【讨论】:

    【解决方案4】:

    既然你关心性能,你能不能试试这个 Perl 解决方案。

    $ perl -lne 'BEGIN{@x=map{chomp;@k=split(/[ ,]/,$_);$kv{"$k[-2] $k[-1]"}="$k[-4]$k[-3]"} qx(cat file1.txt)} /(\S+) (\S+)$/ and $kv{$&} and print $_," ",$kv{$&}, " ",$& ' f
    ile2.txt
    3000135825 302412.50 2316512.50 3667931308 302412.50 2316512.50
    3000135897 303312.50 2316512.50 3671931358 303312.50 2316512.50
    
    $
    

    【讨论】:

      猜你喜欢
      • 2022-01-01
      • 2016-10-23
      • 2020-05-18
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-26
      相关资源
      最近更新 更多