如何用GAWK筛选input1中未在input2出现的行?
问题原因
你的GAWK代码无输出的核心问题是文件名判断逻辑失效:
你在代码中用FILENAME == "input2"和FILENAME == "input1"做判断,但命令行传入的是带路径的文件名(如path/to/input2),FILENAME变量实际存储的是完整路径字符串,和你判断的纯文件名不匹配。这导致:
- 处理
input2时,数组a完全没被填充; - 处理
input1时,输出逻辑的判断条件也不成立,最终没有任何内容输出。
另外,IGNORECASE = 1的设置对数组索引的in判断无效——GAWK中数组索引是精确字符串匹配,该参数仅影响正则匹配和==/!=这类字符串比较操作。
修正方案
以下是两种可靠的GAWK解决方案,按需选择:
方案1:用ARGIND变量区分文件(推荐)
ARGIND是GAWK内置变量,表示当前处理的文件在命令行参数中的索引(第一个文件为1,第二个为2),无需依赖文件名,适配所有路径场景。
忽略大小写匹配版本
gawk ' BEGIN { IGNORECASE = 1 } ARGIND == 1 { a[tolower($0)] = 1 } ARGIND == 2 { if (!(tolower($0) in a)) print > "path/to/output" } ' path/to/input2 path/to/input1
精确匹配版本(不忽略大小写)
gawk ' ARGIND == 1 { a[$0] = 1 } ARGIND == 2 { if (!($0 in a)) print > "path/to/output" } ' path/to/input2 path/to/input1
方案2:用ARGV数组匹配完整文件名
ARGV数组存储了命令行传入的完整文件名(带路径),用FILENAME == ARGV[1]做判断,能准确匹配带路径的文件:
忽略大小写匹配版本
gawk ' BEGIN { IGNORECASE = 1 } FILENAME == ARGV[1] { a[tolower($0)] = 1 } FILENAME == ARGV[2] { if (!(tolower($0) in a)) print > "path/to/output" } ' path/to/input2 path/to/input1
额外说明
- 原代码中的
-F ';'是多余的,因为我们只用到整行内容$0,无需设置字段分隔符,可直接去掉; - 输出文件用
>即可,GAWK会自动在第一次写入时创建/截断文件,后续写入自动追加,无需改用>>。
内容的提问来源于stack exchange,提问作者lyrically wicked
相关产品推荐
相关产品推荐

