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のどこかに表示される可能性があります。
私の期待される解決策:
- 2番目のファイルだけが最初のファイルの列1と比較されます(これは時間がかかります)。
- ファイルポインタを含むスクリプトを使用して、
perl
ファイルの2つの列を比較します。文字列が一致した場合は印刷します。それ以外の場合、最初のファイルの列 1 が 2 番目のファイルの列よりも大きい場合、ファイル 2 が増加して比較されます。逆の場合、ファイル1の列1を増やして比較します。
答え1
join file1 file2
デフォルトでは、各ファイルに対して列1を使用し、そのうち行方不明を無視します。これは欲しいものです。また、ファイルを並べ替える必要がありますが、これはすでにそうです。
答え2
数量ならユニークの要素がfile2
大きすぎない場合、実行可能な解決策は、2つのファイルを処理する古典的なアプローチを使用して、最初にawk
列1の唯一の要素の配列を作成し、列1が配列のメンバーであるかどうかをテストすることです。今file2
file1
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