【问题标题】:bash to get information from two filesbash 从两个文件中获取信息
【发布时间】:2017-03-07 09:23:33
【问题描述】:

我有文件 1:

NM_000014   A2M
NM_000015   NAT2
NM_000016   ACADM
NM_000017   ACADS
NM_000018   ACADVL
NM_000019   ACAT1
NM_000020   ACVRL1
NM_000021   PSEN1
NM_000022   ADA

还有文件2:

NM_000019   
NM_000020   
NM_000020
NM_12345

我需要从我的 file1 中获取信息并将其放入 file2 - 所以创建 file3:

NM_000019   ACAT1
NM_000020   ACVRL1
NM_000020   ACVRL1
NM_12345    NO

注意 - 我无法更改原始排序顺序(所以不要使用 comm 和 diff)。我在file2中有重复行-我需要保留(wc -l file2 == wc -l file3)。如果没有匹配 - 打印NO

我有大约 70K 行,我不需要最快的解决方案。 我的代码只能比较和打印相同的结果。

代码:

#!/bin/bash

while read -r c; do


grep $c file1  | uniq 

done < file2 > file3

【问题讨论】:

    标签: bash shell awk sed


    【解决方案1】:

    使用 awk:

    $ awk 'NR==FNR{a[$1]=$2;next} {print ($1 in a?$1 OFS a[$1]:$1 OFS "NO")}' file1 file2
    NM_000019 ACAT1
    NM_000020 ACVRL1
    NM_000020 ACVRL1
    NM_12345 NO
    

    解释:

    NR==FNR{                                      # process the first file
        a[$1]=$2                                  # hash records to a, $1 as key
        next                                      # skip to next record
    } 
    {                                             # process the second file
        print ($1 in a?$1 OFS a[$1]:$1 OFS "NO")  # print hashed value if found or NO
    
    #   if($1 in a)                               # another way of saying above
    #       print $1, a[$1] 
    #   else 
    #       print $1, "NO"
    }
    

    【讨论】:

    • 为了完整起见,您可以添加awk -v OFS="\t" '#my awk code ....' file1 file2 以使字段由制表符分隔
    • @Aserre 谢谢,没有看到提到的标签,所以我跳过了。
    • @JamesBrown 感谢您提供完美的 awk 解决方案。非常感兴趣的是,您的解决方案中的条件适用于 wc -l file2 == wc -l file3 !!
    • @Geroge 是的。对于 file2 中的每条记录,脚本会输出另一条记录。
    【解决方案2】:

    所以基本上你有一个带有模式的文件,还有一个你想使用这些模式搜索的文件:

    #!/bin/bash
    
    for PATTERN in $(cat $2); do
        TMP=$(egrep $PATTERN $1)
        if [ ! -z "$TMP" ]; then
            echo "$TMP" 
        else
            echo "$PATTERN NO"
        fi
    done
    

    快速测试:

    $ bash filter.sh file1 file2
    NM_000019   ACAT1
    NM_000020   ACVRL1
    NM_000020   ACVRL1
    NM_12345 NO
    

    【讨论】:

    【解决方案3】:

    尝试将这个if 语句添加到您的代码中:

    if ! grep -q $i fileone ; then
      echo -e $i "   NO"
    fi
    

    例如:

    #!/bin/bash
    while read -r c; do grep $c fileone  | uniq; done < filetwo
    for i in $(cat filetwo)
    do
      if ! grep -q $i fileone ; then
        echo -e $i "   NO"
      fi
    done
    

    如果file1中的file2行不匹配,它将打印NO。

    【讨论】:

      【解决方案4】:

      尝试粘贴命令。这是不如 awk 高贵的形式。我更喜欢 awk 但粘贴命令应该对你有所帮助。

      粘贴文件1 文件2 文件3...等..文件N

      您可以像往常一样将命令输出重定向到文件。

      粘贴 file1 file2 file3... etc ..fileN > fileN+1(或其他)

      那是逐行读取文件并按顺序并行输出。

      就是这样。它不是很优雅,但有时​​它非常有用,直到您找到不同的方法来获得所需的结果。

      希望有帮助

      【讨论】:

      • 感谢您的分享。我认为只有在对我的数据进行排序时才能使用粘贴,不是吗?问题是,我需要保持输入排序顺序..
      • 粘贴命令不会改变数据的顺序,因为数据在文件中,逐行打印它们连接不同的文件。也就是说,第一行文件1,第一行文件2.....如果您的数据先前已排序,则粘​​贴命令不会改变它。
      猜你喜欢
      • 2019-07-17
      • 1970-01-01
      • 1970-01-01
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 1970-01-01
      • 2015-07-04
      相关资源
      最近更新 更多