考虑以下文件:
file1
:
boo,8,1024
foo,7,2048
file2
:
foo,0,24,154
noo,0,10,561
file3
:
24,154,7,1024,0
我需要的是去文件1并检查是否$2==7
;如果为 true,则采用$1
和from$2
$3
文件1;现在我必须比较是否$1
来自文件1等于$1
从文件2;如果是真的,我必须采取$3
和$4
文件2不存在于文件1,那么我必须去文件3并检查是否$1
来自文件3等于$3
从文件2,并$2
从文件3等于$4
从文件2;如果是,那么我必须检查是否$2
来自文件1等于$3
从文件3,那么如果这个条件为真,我必须$3
比较文件1与$4
来自文件3,如果$3
从文件1比$4
从文件3。
我尝试了以下脚本:
cat [file1] [file2] [file3] |
awk -F,
'{if(NF==3)
{if($2==7){a[$1]=$1; b[$1]=$2; c[$1]=$3}
}else
{if(NF==4){if(a[$1]==$1){d[$3]=$3; e[$4]=$4}
}else
{if(NF==5){if(d[$1]==$1 && e[$2]==$2){print a[$1], b[$1], c[$1], d[$1]}}
}
}
}'
期望的输出是:
foo,7,2048,24,154,1024
答案1
这对我有用:
awk -F, 'FNR==1{++f} \
f==1 && $2==7 {a1[$1]++; a2[$2]=$3; o=$0} \
f==2 && a1[$1] {o=o","$3","$4; a3[$3]=$4} \
f==3 && a3[$1] && $2==a3[$1] && a2[$3] && $4<a2[$3] {print o}' \
file1 file2 file3
解释:
- 第一行 (
FNR==1{++f}
) 增加文件索引,以便稍后确定我们位于 1-3 的哪个文件中。 - 文件1:如果
$2
等于7
a1
使用$1
索引、a2
索引$2
和$3
值填充数组- 写下
o
变量(输出)的前 3 个字段
- 文件2:if
$1
等于(file2
之前写在)$1
file1
a1
- 将
$3
和附加$4
到输出变量o
。 a3
使用$3
索引和$4
值填充数组。
- 将
- 文件3:如果:
$1
等于 file2s$3
(索引a3
)$2
等于 file2s$4
( 的值a3
)$3
等于 file1s$2
(索引a2
)$4
低于 file1s$3
( 的值a2
)
- 然后:
- 打印 的值
o
。
- 打印 的值
答案2
TXR解决方案:
@(repeat)
@id,@val0,@val1
@ (next)
@ (skip)
@id,@nil,@val2,@val3
@ (next)
@val2,@val3,@val0,@val4,@val5
@ (require (< (int-str val4) (int-str val1)))
@ (output)
@id,@val0,@val1,@val2,@val3,@val4
@ (end)
@(end)
跑步:
$ txr join.txr file1 file2 file3
foo,7,2048,24,154,1024
但精明的观察者会注意到,代码中的任何地方都没有指定 7,它只出现在输出中!这是因为代码实际上遍历了file1
和中的所有记录打印满足匹配和约束的所有组合。样本数据中唯一带有val0
being 的数据7
。
如果找到更多组合,则可能会被限制为7
如下所示的组合:
$ txr -Dval0=7 join.txr file1 file2 file3
foo,7,2048,24,154,1024
# how about 6?
$ txr -Dval0=6 join.txr file1 file2 file3
# no output
TXR 模式提取语言在这里提供了一种大模式匹配,通过重复变量名、跨越多个文件、具有多行提取模式和非文本约束,以及嵌入的副作用(如输出等),隐式反向引用。
接受awk解决方案仔细翻译了TXR Lispawk
宏:
(awk (:begin (set fs "," ofs ","))
(:let o (a1 (hash :equal-based)) (a2 (hash)) (a3 (hash)))
(t (mf [orf int-str identity])) ;; map those fields to integers, which can be
((and (= arg 1) (= [f 1] 7)) (inc [a1 [f 0] 0])
(set [a2 [f 1]] [f 2])
(set o rec))
((and (= arg 2) [a1 [f 0]]) (set o `@o,@[f 2],@[f 3]`)
(set [a3 [f 2]] [f 3]))
((and (= arg 3)
[a3 [f 0]]
(= [f 1] [a3 [f 0]])
[a2 [f 2]]
(< [f 3] [a2 [f 2]])) (prn o)))
跑步:
$ txr awkit.tl file1 file2 file3
foo,7,2048,24,154
,1024
输出中缺少所需部分;原来的“Awk Classic”有这种行为。