我有2个文件..
文件1:
abc|123|check
def|456|map
ijk|789|globe
lmn|101112|equator
文件2:
check
map
equator
globe
AWK 函数应该将 file1 的第三列(剪切第三列和排序后)与 file2 排序的内容进行比较
- 如果所有行都匹配,则应返回 1
- 否则应该返回 2
答案1
function are_all_there {
local num_diff=$(comm -3 <(cut -d'|' -f3 "$1" | sort) <(sort "$2") | wc -l)
(( num_diff == 0 )) && return 1 || return 2
}
答案2
根据您的评论,这似乎awk
不是您唯一的选择。所以这是一个非 awk 方法。
你没有提到需要独特的问题中的比较,但您uniq
在评论中的示例中使用了。如果你不需要独特的匹配,只需删除排序选项即可-u
。 (测试于bash
)。
(($(comm -3 <( cut -d'|' -f3 file1 | sort -u ) \
<( sort -u file2 ) | wc -l))) && echo 2 - not all match ||
echo 1 - all match
或者,使用awk
进行最终比较 - 在paste
.
paste <( cut -d'|' -f3 file1 | sort -u ) \
<( sort -u file2 ) |
awk '$1!=$2{m=2; exit}
END{ if(m == 2){print "2 - not all match"; exit;}
print "1 - all match";}'
或者,awk
比较两个输入文件
awk '{if(NR == FNR){a[NR]=$1}
else{ if($1 != a[NR]){m=2; exit}}}
END{ if(m == 2){print "2 - not all match"; exit;}
print "1 - all match";}' \
<( cut -d'|' -f3 file1 | sort -u ) \
<( sort -u file2 ) |
答案3
有趣的CS答案!我们实际上不需要对任何东西进行排序,因为这是纯集比较。
输入文件是一个集合的表示,其中元素是成对的。例如,如果该行在foo
中出现 3 次file1
,则表示元素 < foo
, 3>。如果file2
包含foo
3次,则意味着两个集合都包含该元素。如果file2
不包含foo
或包含不同次数的重复foo
,则表示不包含 < foo
, 3> 的集合。
此外,请注意,像 < , 3> 这样的一组对foo
可以用将键映射foo
到 3 的哈希来表示。
TXR Lisp awk 宏:
(awk (:begin (set fs "|"))
(:let (h1 (hash :equal-based)) (h2 (hash :equal-based)))
((= arg 1) (inc [h1 [f 2] 0]))
((= arg 2) (inc [h2 rec 0]))
(:end (exit (equal h1 h2))))
如果文件按照所需方式相等,则会产生成功终止状态,否则会产生失败状态:
$ txr comp.tl 文件1 文件2 $回声$? 0 $回显映射>>文件2 $ txr comp.tl 文件1 文件2 $回声$? 1
如果我们想通过解析“1”或“2”输出来使调用程序变得复杂,可以通过更改规则来完成:end
:
(:end (prn (if (equal h1 h2) "1" "2")))
这是常规 awk 中的情况。主要区别在于我们有简洁的语法,我们不必定义我们引用的任何变量;另一方面,我们必须编写一对循环来比较两个关联数组,并生成我们自己的arg
变量来跟踪我们正在处理哪个文件。 (GNU Awk 有用ARGIND
于此目的的。)
BEGIN { FS = "|" }
FNR == 1 { arg++ }
arg == 1 { h1[$3]++; }
arg == 2 { h2[$0]++; }
END { same = 1
for (i in h1)
if (h1[i] != h2[i]) {
same = 0
break
}
if (same)
for (i in h2)
if (h2[i] != h1[i]) {
same = 0
break
}
print same ? "1" : "2"; }