使用Linux匹配来自两个文件的数字

时间:2014-04-28 04:40:48

标签: linux

使用Linux命令或脚本,我想比较两个文件中的数据。第一个文件有一系列7个数字,后跟一行上的名称,文件中有几行数字和名称。这些数字不能在同一行重复,但可以在另一行中找到,并且将按顺序列在每一行。

File1示例:

01 02 03 04 05 06 07姓名1

11 12 13 14 15 16 17姓名2

01 03 05 11 12 14 16姓名3

...

我想知道File1中的一行数字与File2中的另一组数字相匹配。 File2中的数字不重复,将按顺序排序。

File2示例:

01 02 03 04 05 11 12 13 14 15 16 18 20

只要File1中的一行数字与File2中的任何数字匹配,我希望显示匹配的行,包括名称。

输出示例:

01 03 05 11 12 14 16姓名3

如果没有匹配,我想显示“No Match”或类似内容。

我是Linux和脚本文件的新手,并感谢所有帮助。谢谢。

2 个答案:

答案 0 :(得分:1)

使用Awk这很容易。让我们把这个零碎。

NR==FNR { for (i=1; i<=NF; ++i) a[$i]=1; next }

当我们读取第一个输入文件时,NR==FNR条件为真。我们遍历输入字段,并在关联数组a中为每个字段分配一个键。现在包含第一个文件的输入字段(运行时我们将确保File2)。

在另一个文件的行上,循环遍历最后一个字段(我们跳过最后一个字段,其中包含标识符,如Name2)。如果任何值不在a中,请放弃此行。

{ for (i=1; i<NF; i++) if (! ($i in a)) next }

否则,请打印。

1

(孤独的1是一个awk习语,如果我们在脚本中落到这个部分,它会打印输入。这是一个平常为真的条件,没有动作;默认动作是打印输入线。)

在shell脚本片段中收集所有内容,我们获取

awk 'NR==FNR { for (i=1; i<=NF; ++i) a[$i] = 1; next }
    { for (i=1; i<NF; i++) if (! ($i in a)) next } 1' File2 File1

这假设File2只包含一行。如果你想扩展到多行,Awk的功能会有点紧张;在这一点上,也许可以考虑切换到Perl或Python(或者你熟悉的其他任何东西)。 Awk的吸引力在于它很简单 - 您可以在一天内学习它,并在一周内编写好的脚本。

答案 1 :(得分:0)

这个(相当难看的)bash脚本将在给定的样本数据上生成正确的结果:

# Read numbers against which to match from File2 into array.
read -a match_array <<< "$(cat File2)"

# Traverse each line in File1
while read -a line
do
  if [ "$line" != "" ]
  then

    # Counter for the number of matches
    match=0

    # Strip off the name on the end, leaving only numbers to match
    for n in "${line[@]:0:7}"
    do
      for m in "${match_array[@]}"
      do
        if [ "$n" == "$m" ]
        then
          # Successfully matched a number, increment counter.
          match=$(($match + 1))
        fi
      done

      # Correct number of matches
      if [ "$match" == "7" ]
      then
        echo ${line[@]}
      fi
    done
  fi
done < File1