2013-06-21 80 views
18

我有2個文件。第一個文件包含數據庫中表的元組的行ID列表。 而第二個文件包含查詢的「where」子句中的這些行ID的SQL查詢。在UNIX中從另一個文件中查找一個文件的內容

例如:

文件1

1610657303 
1610658464 
1610659169 
1610668135 
1610668350 
1610670407 
1610671066 

文件2

update TABLE_X set ATTRIBUTE_A=87 where ri=1610668350; 
update TABLE_X set ATTRIBUTE_A=87 where ri=1610672154; 
update TABLE_X set ATTRIBUTE_A=87 where ri=1610668135; 
update TABLE_X set ATTRIBUTE_A=87 where ri=1610672153; 

我要讀文件1和文件2搜索所有匹配的行ID的SQL命令來自文件1並將這些SQL查詢轉儲到第三個文件中。

文件1有1,00,000個條目,文件2包含文件1的條目的10倍,即1,00,0000。我使用grep -f File_1 File_2 > File_3。但這個速度非常慢,每小時1000個條目。

有沒有更快的方法來做到這一點?

+0

盡一切所使用文件1中提到的行ID的查詢最終在同一個輸出文件中,還是您希望文件1中的每個行ID都有單獨的文件? –

+0

您是否允許對ID上的文件進行排序?或者訂單是否需要保存? – fizzer

+0

只有一個輸出文件。 每次來自文件1的條目都與文件2中的條目匹配時,文件2的該條目應該被轉儲到輸出文件中。文件1和文件2中的條目是唯一的。在任何文件中都沒有重複的行。 – Tirthankar

回答

13

一種方式與awk

awk -v FS="[ =]" 'NR==FNR{rows[$1]++;next}(substr($NF,1,length($NF)-1) in rows)' File1 File2 

這應該很快。在我的機器上,花了不到2秒的時間創建了一百萬個條目的查詢,並將其與300萬行進行比較。

機規格:上述

Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz (8 cores) 
98 GB RAM 
+1

+1。 awk爲勝利。 –

+1

這個單線程很精彩:) –

+1

如果您要指定運行該命令所需的時間,可能需要包含機器規格。 – doubleDown

0

也許嘗試AWK和使用數量從文件1,例如簡單的腳本,一鍵

第一個腳本會產生awk腳本:
的awk -f script1.awk

 
{ 
    print "\$0 ~ ",$0,"{ print \$0 }" > script2.awk; 
} 

,然後調用SCRIPT2 .awk與文件

+0

但是,這也會導致文件1和文件2上的多個文件讀取。難道你不認爲這也會變慢。 – Tirthankar

+0

是的,但是如果您只讀了一次file1並創建一個大的regexp,然後檢查file2中的所有行,則此regexp將只讀取一次每個文件。 – Damian0o

1

我可能會遺漏一些東西,但是僅僅遍歷file1中的ID和每個ID,grep file2並將匹配存儲在第三個文件?即

for ID in `cat file1`; do grep $ID file2; done > file3 

這不是非常有效率(因爲file2會被重複讀取),但它可能已經足夠好了。如果你想要更快的速度,我會建議使用更強大的腳本語言,讓你可以將file2讀入地圖,該地圖可以快速識別給定ID的行。

這裏有這種想法的Python版本:

queryByID = {} 

for line in file('file2'): 
    lastEquals = line.rfind('=') 
    semicolon = line.find(';', lastEquals) 
    id = line[lastEquals + 1:semicolon] 
    queryByID[id] = line.rstrip() 

for line in file('file1'): 
    id = line.rstrip() 
    if id in queryByID: 
    print queryByID[id] 
+0

我也使用Perl,但它沒有幫助: my $ input_ri_file =「input_RI.csv」; my $ input_sql_file =「SQL_file.sql」; my $ output_sql_file =「Out_SQL_file.sql」; open(SQLFILE,「<$ input_sql_file」); foreach(){ push @ lin,$ _除非($ _ eq「\ n」); } close $ SQLFILE; open(RILIST,「<$ input_ri_file」); foreach(){ push @ ri_list,$ _ unless($ _ eq「\ n」); } close $ RILIST; open(FINALSQLFILE,「> $ output_sql_file」); (ri_list){ chomp $ ri; (@lin) if($ _ =〜/ $ ri /)打印FINALSQLFILE $ _; } } } close FINALSQLFILE; – Tirthankar

+0

@Tirthankar:我剛剛添加了一個Python版本,這有幫助嗎?該腳本需要兩個文件'file1'和'file2'。它將匹配打印到標準輸出,因此您可以將其重定向到文件。 –

+1

@Tirthankar你可能想用pastebin代替轉儲代碼到註釋中...... :-) –

22

你不需要正則表達式,所以grep -F -f file1 file2

+0

OP說他已經試過這個,但它太慢了。 –

+7

但沒有-F屬性 – Damian0o

+0

我有點有興趣如何對[JS的awk解決方案](http://stackoverflow.com/a/17236091/1743811)坑,但我懶得複製OP的條件。 – doubleDown

1

我建議使用一種編程語言如Perl,Ruby或Python。

在Ruby中,解決閱讀這兩個文件(f1f2)只是一次可能是:

idxes = File.readlines('f1').map(&:chomp) 

File.foreach('f2') do | line | 
    next unless line =~ /where ri=(\d+);$/ 
    puts line if idxes.include? $1 
end 

或用Perl

open $file, '<', 'f1'; 
while (<$file>) { chomp; $idxs{$_} = 1; } 
close($file); 

open $file, '<', 'f2'; 
while (<$file>) { 
    next unless $_ =~ /where ri=(\d+);$/; 
    print $_ if $idxs{$1}; 
} 
close $file; 
1

的AWK/grep的解決方案很慢或我的機器存儲器餓(文件1個10^6行,file2的10^7行)。所以我想出了一個使用sqlite3的SQL解決方案。

打開文件2成CSV格式的文件,其中第一場是後ri=

cat file2.txt | gawk -F= '{ print $3","$0 }' | sed 's/;,/,/' > file2_with_ids.txt 

創建兩個表的值:從文件1

sqlite> CREATE TABLE file1(rowId char(10)); 
sqlite> CREATE TABLE file2(rowId char(10), statement varchar(200)); 

導入行ID:

sqlite> .import file1.txt file1 

使用「準備」版本導入file2中的語句:

sqlite> .separator , 
sqlite> .import file2_with_ids.txt file2 

選擇全部ONY表file2與匹配的ROWID表file1語句:

sqlite> SELECT statement FROM file2 WHERE file2.rowId IN (SELECT file1.rowId FROM file1); 

文件3可以通過發出SELECT語句前輸出重定向到一個文件,可以輕鬆創建:

sqlite> .output file3.txt 

測試數據:

sqlite> select count(*) from file1; 
1000000 
sqlite> select count(*) from file2; 
10000000 
sqlite> select * from file1 limit 4; 
1610666927 
1610661782 
1610659837 
1610664855 
sqlite> select * from file2 limit 4; 
1610665680|update TABLE_X set ATTRIBUTE_A=87 where ri=1610665680; 
1610661907|update TABLE_X set ATTRIBUTE_A=87 where ri=1610661907; 
1610659801|update TABLE_X set ATTRIBUTE_A=87 where ri=1610659801; 
1610670610|update TABLE_X set ATTRIBUTE_A=87 where ri=1610670610; 

沒有創建任何索引,select語句在AMD A8 1.8HGz 64位Ubuntu 12.04機器上花費了大約15秒。

-1

##報告包含在<文件1中的任何行>在<文件中缺少2>

IFS=$(echo -en "\n\b") && for a in $(cat < file 1>); 
do ((\!$(grep -F -c -- "$a" < file 2>))) && echo $a; 
done && unset IFS 

或做提問者想,脫下否定和重定向

(IFS=$(echo -en "\n\b") && for a in $(cat < file 1>); 
do (($(grep -F -c -- "$a" < file 2>))) && echo $a; 
done && unset IFS) >> < file 3> 
+0

你可以在我的博客中看到我最近做過的shell腳本:http://scriptsandoneliners.blogspot.com/2014/08/blog-post.html – 2014-08-12 23:47:00

相關問題