Unix 命令在另一个 file2 中搜索 file1 id 并将结果写入 file3
Unix command to search file1 id in another file2 and write result to a file3
我必须从一个文件中读取 ID 并在第二个 xml 文件中搜索它,如果找到则将整行写入第三个文件。文件 1 为 111 MB,文件 2 为 40 GB
File1.xml
id1
id2
id5
File2.xml
<employees>
<employee><id>id1</id><name>test1</name></employee>
<employee><id>id2</id><name>test2</name></employee>
<employee><id>id3</id><name>test3</name></employee>
<employee><id>id4</id><name>test4</name></employee>
<employee><id>id5</id><name>test5</name></employee>
<employee><id>id6</id><name>test6</name></employee>
</employees>
File3.xml : 结果
<employee><id>id1</id><name>test1</name></employee>
<employee><id>id2</id><name>test2</name></employee>
<employee><id>id5</id><name>test5</name></employee>
我用 grep 试过了
grep -i -f file1.xml file2.xml >> file3.xml
但它给出内存耗尽错误。
我用循环和 awk 命令尝试的另一种方法。
#while read -r id;do
#awk -v pat="$id" '[=14=]~pat' file2.xml >> file3.xml
#done < file1.xml
它也花了太多时间。
最好的解决方案是什么。
使用您显示的示例,请尝试以下 awk
代码。在 GNU awk
.
中编写和测试
awk -v FPAT='<id>[^<]*</id>' '
FNR==NR{
arr["<id>"[=10=]"</id>"]
next
}
( in arr)
' file1.xml file2.xml
解释:为以上添加详细解释。
awk -v FPAT='<id>[^<]*</id>' ' ##Starting awk program and setting FPAT to <id>[^<]*<\/id>
FNR==NR{ ##Checking condition which will be TRUE when file1.xml is being read.
arr["<id>"[=11=]"</id>"] ##Creating an array arr which has index of <id> [=11=] </id> here.
next ##next will skip all further statements from here.
}
( in arr) ##Checking condition if is present in arr then print that line.
' file1.xml file2.xml ##Mentioning Input_file names here.
这应该适用于任何 awk 版本:
awk 'FNR == NR {
seen["<id>" "</id>"]
next
}
match([=10=], /<id>[^<]*<\/id>/) && substr([=10=], RSTART, RLENGTH) in seen
' file1 file2
<employee><id>id1</id><name>test1</name></employee>
<employee><id>id2</id><name>test2</name></employee>
<employee><id>id5</id><name>test5</name></employee>
我必须从一个文件中读取 ID 并在第二个 xml 文件中搜索它,如果找到则将整行写入第三个文件。文件 1 为 111 MB,文件 2 为 40 GB
File1.xml
id1
id2
id5
File2.xml
<employees>
<employee><id>id1</id><name>test1</name></employee>
<employee><id>id2</id><name>test2</name></employee>
<employee><id>id3</id><name>test3</name></employee>
<employee><id>id4</id><name>test4</name></employee>
<employee><id>id5</id><name>test5</name></employee>
<employee><id>id6</id><name>test6</name></employee>
</employees>
File3.xml : 结果
<employee><id>id1</id><name>test1</name></employee>
<employee><id>id2</id><name>test2</name></employee>
<employee><id>id5</id><name>test5</name></employee>
我用 grep 试过了
grep -i -f file1.xml file2.xml >> file3.xml
但它给出内存耗尽错误。
我用循环和 awk 命令尝试的另一种方法。
#while read -r id;do
#awk -v pat="$id" '[=14=]~pat' file2.xml >> file3.xml
#done < file1.xml
它也花了太多时间。 最好的解决方案是什么。
使用您显示的示例,请尝试以下 awk
代码。在 GNU awk
.
awk -v FPAT='<id>[^<]*</id>' '
FNR==NR{
arr["<id>"[=10=]"</id>"]
next
}
( in arr)
' file1.xml file2.xml
解释:为以上添加详细解释。
awk -v FPAT='<id>[^<]*</id>' ' ##Starting awk program and setting FPAT to <id>[^<]*<\/id>
FNR==NR{ ##Checking condition which will be TRUE when file1.xml is being read.
arr["<id>"[=11=]"</id>"] ##Creating an array arr which has index of <id> [=11=] </id> here.
next ##next will skip all further statements from here.
}
( in arr) ##Checking condition if is present in arr then print that line.
' file1.xml file2.xml ##Mentioning Input_file names here.
这应该适用于任何 awk 版本:
awk 'FNR == NR {
seen["<id>" "</id>"]
next
}
match([=10=], /<id>[^<]*<\/id>/) && substr([=10=], RSTART, RLENGTH) in seen
' file1 file2
<employee><id>id1</id><name>test1</name></employee>
<employee><id>id2</id><name>test2</name></employee>
<employee><id>id5</id><name>test5</name></employee>