在 linux 中使用 Awk 比较两个文件
Comparing two files using Awk in linux
我有两个文件,文件A和文件B。文件A的结构如下所示:
3314530275|76|1|20240422045006|
3335984469|64|2|20150804235959|
3367892381|203|3|20141025235959|
3369039388|203|4|20131219235959|
第二个文件B的内容如下:
3314530275|2000|999000000073101614|0|20370101000000|76|
3314530275|2000|999000000073101614|0|20370101000000|76|
3369039388|2000|812000002628721|-112|20360101235959|203|
3335984469|5037|5210367877660|180|20150213000000|64|
3335984469|5048|5210367877661|6|20150213000000|64|
3335984469|2000|812000002629182|1913|20360101235959|64|
3367892381|5014|5210365185964|419430400|20150308000000|203|
3367892381|5044|5210365185965|226020|20150308000000|203|
3367892381|2000|817000102009605|0|20360101235959|203|
脚本首先检查文件A,如果第三个字段($3)等于2,它应该存储第一列($1)和第四列($4)的值。
之后它将检查(第二个文件的)$1 值是否存在于我们在第一步中存储的值中。
如果该值存在并且第二个字段等于 2000,它应该打印 $1,$2,$4,(我们从第一个文件中获取并存储的第四列的值)
如果值存在并且第二个字段不等于 2000,它应该打印 $1,$2,$4,$5
上述案例中的示例输出:
3335984469|5037|180|20150213000000|
3335984469|5048|6|20150213000000|
3335984469|2000|1913|20150804235959|
这是我目前拥有的:
awk -F \| 'FNR==NR {if( == 2) a[] = ; next} ( in a) {if(==2000) print"|""|""|"a[]"|"} ( in a) {if(!=2000) print"|""|""|""|"} ' FileA FileB > Output_File
任何帮助将不胜感激。
如果文件 A 的内容正确,您的脚本将按原样运行(FileA 中的 335984469
应该是 3335984469
,即多一个前导 3
。)但它可以简化为:
$ cat tst.awk
BEGIN{ FS=OFS="|" }
FNR==NR { if (==2) a[] = ; next }
in a { print , , , (==200 ? a[] : ), "" }
$ awk -f tst.awk fileA fileB
3335984469|5037|180|20150213000000|
3335984469|5048|6|20150213000000|
3335984469|2000|1913|20360101235959|
如果您觉得有用,请随意将其全部塞回一行。
如果上述方法不起作用,请检查两个输入文件中是否存在控制字符,最有可能的是 control_Ms Microsoft 在其工具创建文件时慷慨捐赠的字符。您可以使用 cat -v
检查它们并使用 dos2unix
或类似的方法删除它们。
awk 'BEGIN{FS=OFS="|"};FNR==NR{if(==2){a[]=;next}};{if( in a && ==2000 ){print ,,,a[]}else if ( in a && !=2000){print ,,,}}' 'fileA' 'fileB'
我对您的命令行进行了调整以获得上面的命令行
if( in a && ==2000 ){print ,,,a[]}
else if ( in a && !=2000){print ,,,}}
结果
3335984469|5037|180|20150213000000
3335984469|5048|6|20150213000000
3335984469|2000|1913|20150804235959
我有两个文件,文件A和文件B。文件A的结构如下所示:
3314530275|76|1|20240422045006|
3335984469|64|2|20150804235959|
3367892381|203|3|20141025235959|
3369039388|203|4|20131219235959|
第二个文件B的内容如下:
3314530275|2000|999000000073101614|0|20370101000000|76|
3314530275|2000|999000000073101614|0|20370101000000|76|
3369039388|2000|812000002628721|-112|20360101235959|203|
3335984469|5037|5210367877660|180|20150213000000|64|
3335984469|5048|5210367877661|6|20150213000000|64|
3335984469|2000|812000002629182|1913|20360101235959|64|
3367892381|5014|5210365185964|419430400|20150308000000|203|
3367892381|5044|5210365185965|226020|20150308000000|203|
3367892381|2000|817000102009605|0|20360101235959|203|
脚本首先检查文件A,如果第三个字段($3)等于2,它应该存储第一列($1)和第四列($4)的值。
之后它将检查(第二个文件的)$1 值是否存在于我们在第一步中存储的值中。
如果该值存在并且第二个字段等于 2000,它应该打印 $1,$2,$4,(我们从第一个文件中获取并存储的第四列的值)
如果值存在并且第二个字段不等于 2000,它应该打印 $1,$2,$4,$5
上述案例中的示例输出:
3335984469|5037|180|20150213000000|
3335984469|5048|6|20150213000000|
3335984469|2000|1913|20150804235959|
这是我目前拥有的:
awk -F \| 'FNR==NR {if( == 2) a[] = ; next} ( in a) {if(==2000) print"|""|""|"a[]"|"} ( in a) {if(!=2000) print"|""|""|""|"} ' FileA FileB > Output_File
任何帮助将不胜感激。
如果文件 A 的内容正确,您的脚本将按原样运行(FileA 中的 335984469
应该是 3335984469
,即多一个前导 3
。)但它可以简化为:
$ cat tst.awk
BEGIN{ FS=OFS="|" }
FNR==NR { if (==2) a[] = ; next }
in a { print , , , (==200 ? a[] : ), "" }
$ awk -f tst.awk fileA fileB
3335984469|5037|180|20150213000000|
3335984469|5048|6|20150213000000|
3335984469|2000|1913|20360101235959|
如果您觉得有用,请随意将其全部塞回一行。
如果上述方法不起作用,请检查两个输入文件中是否存在控制字符,最有可能的是 control_Ms Microsoft 在其工具创建文件时慷慨捐赠的字符。您可以使用 cat -v
检查它们并使用 dos2unix
或类似的方法删除它们。
awk 'BEGIN{FS=OFS="|"};FNR==NR{if(==2){a[]=;next}};{if( in a && ==2000 ){print ,,,a[]}else if ( in a && !=2000){print ,,,}}' 'fileA' 'fileB'
我对您的命令行进行了调整以获得上面的命令行
if( in a && ==2000 ){print ,,,a[]}
else if ( in a && !=2000){print ,,,}}
结果
3335984469|5037|180|20150213000000
3335984469|5048|6|20150213000000
3335984469|2000|1913|20150804235959