列に基づいて2つのファイルを比較して印刷します。

列に基づいて2つのファイルを比較して印刷します。

400,000行の大きなファイルが2つあります。 2番目のファイルの列1と最初のファイルの列1を再帰的に比較したいと思います。一致したら、行全体を印刷したいと思います。ソートされたファイルです。

file 1:
  name   values
  aaa    10
  aab    acc
  aac    30
  aac    abc

file2:
  aaa
  aac
  aac
  aad

ファイルには400,000行が含まれているため、処理に時間がかかります。

私の現在の解決策は次のとおりです。

#!/bin/ksh
while read line
do
var=`echo $line `
grep "$var" file1 >> /dev/null
if [ $? -eq 0 ]
then
grep "$var" file1 >> present
else
echo " $line missing " > missing
fi
done < "file2"

ここで使用しているので、grep値が予想される列1ではなくファイル1のどこかに表示される可能性があります。

私の期待される解決策:

  1. 2番目のファイルだけが最初のファイルの列1と比較されます(これは時間がかかります)。
  2. ファイルポインタを含むスクリプトを使用して、perlファイルの2つの列を比較します。文字列が一致した場合は印刷します。それ以外の場合、最初のファイルの列 1 が 2 番目のファイルの列よりも大きい場合、ファイル 2 が増加して比較されます。逆の場合、ファイル1の列1を増やして比較します。

答え1

join file1 file2

デフォルトでは、各ファイルに対して列1を使用し、そのうち行方不明を無視します。これは欲しいものです。また、ファイルを並べ替える必要がありますが、これはすでにそうです。

答え2

数量ならユニークの要素がfile2大きすぎない場合、実行可能な解決策は、2つのファイルを処理する古典的なアプローチを使用して、最初にawk列1の唯一の要素の配列を作成し、列1が配列のメンバーであるかどうかをテストすることです。今file2file1

awk 'FNR==NR {a[$1]++}; FNR!=NR && a[$1]' file2 file1

連想配列を使用する同等のアプローチbash 4+は次のとおりです。

#!/bin/bash

declare -A a

while read col1 _ ; do
  ((a[$col1]++))
done < file2

while IFS= read -r line; do
  # compare only with 1st column of second file
  read -r col1 _ <<< "$line"
  [[ -n "${a[$col1]}" ]] && printf "$line\n"
done < file1

答え3

これがあなたが探しているものですか?私はcutリストをそれぞれ1つの列を含む配列に分割することに慣れています。これは、列がタブで区切られていると仮定します。 optionsを指定して、区切り文字の切り捨ての使用を変更できます-d。下線に分割: cut -d '_'

    #!/bin/bash

    FILE1='somefile'
    FILE2='someotherfile'

    # File 1, column 1
    f1c1=($(cut -f1 -s $FILE1))
    # File 1, column 2
    #f1c2=($(cut -f2 -s $FILE1))

    # File 2, column 1
    f2c1=($(cut -f1 -s $FILE2))
    # File 2, column 2
    #f2c2=($(cut -f2 -s $FILE2))

    # Looping through all items in file 1 column 1
    for x in "${f1c1[@]}"
    do
        # For each item in f1c1, check all items in f2c1 for a match
        for y in "${f2c1[@]}"
        do
            if [[ $x == $y ]]
            then
                # The items matched!
                echo $x
                # Breaking out of the loop (no need to check for more than one
                # match, right?)
                break
            fi
        done
    done

関連情報