我有两个 2D 数组文件可以用bash
读取。
我想做的是提取两个文件中的元素。
这两个文件包含不同的行 x 列,例如:
文件1.txt (NX7)
NO DESC ID TYPE W S GRADE
1 AAA 20 AD 100 100 E2
2 BBB C0 U 200 200 D
3 CCC 9G R 135 135 U1
4 DDD 9H Z 246 246 T1
5 EEE 9J R 789 789 U1
.
.
.
文件2.txt (MX3)
DESC W S
AAA 100 100
CCC 135 135
EEE 789 789
.
.
.
这是我想做的:
提取 file2 的 DESC 列中的元素.txt然后在 file1.txt 中找到相应的元素。
提取文件2的此类行中的W,S元素.txt然后在file1.txt的此类行中找到相应的W,S元素。
如果是
[W1==W2 && S1==S2];
那么echo "${DESC[colindex]} ok";
其他echo "${DESC[colindex]} NG"
如何使用 bash 将此类文件读取为 2D 数组,或者有什么方便的方法可以做到这一点?
bash 不支持 2D 数组。您可以通过生成一维数组变量(如 array1
、array2
等)来模拟它们。
假设 DESC 是一个键(即没有重复值)并且不包含任何空格:
#!/bin/bash
# read data from file1
idx=0
while read -a data$idx; do
let idx++
done <file1.txt
# process data from file2
while read desc w2 s2; do
for ((i=0; i<idx; i++)); do
v="data$i[1]"
[ "$desc" = "${!v}" ] && {
w1="data$i[4]"
s1="data$i[5]"
if [ "$w2" = "${!w1}" -a "$s2" = "${!s1}" ]; then
echo "$desc ok"
else
echo "$desc NG"
fi
break
}
done
done <file2.txt
为简洁起见,省略了利用排序顺序等优化。
如果文件实际上包含标头NO DESC ID TYPE ...
则在处理之前使用 tail -n +2
将其丢弃。
也可以使用更优雅的解决方案,避免读取内存中的整个文件。不过,这应该只与非常大的文件相关。
如果不需要保留行顺序(可以排序),也许这就足够了:
join -2 2 -o 1.1,1.2,1.3,2.5,2.6 <(tail -n +2 file2.txt|sort) <(tail -n +2 file1.txt|sort) |
sed 's/^([^ ]*) ([^ ]*) ([^ ]*) 2 3/1 OK/' |
sed '/ OK$/!s/([^ ]*) .*/1 NG/'
对于文件 1.txt
NO DESC ID TYPE W S GRADE
1 AAA 20 AD 100 100 E2
2 BBB C0 U 200 200 D
3 CCC 9G R 135 135 U1
4 DDD 9H Z 246 246 T1
5 EEE 9J R 789 789 U1
和文件2.txt
DESC W S
AAA 000 100
CCC 135 135
EEE 789 000
FCK xxx 135
生产:
AAA NG
CCC OK
EEE NG
解释:
- 跳过两个文件中的标题行 -
tail +2
-
sort
两个文件 -
join
两个文件中所需的列到一个表中,例如,在结果中将仅显示具有共同DESC字段的行
像下一个:
AAA 000 100 100 100
CCC 135 135 135 135
EEE 789 000 789 789
- 在 2-4 列和 3-5 列中具有相同值的行中,将除第一列以外的每列替换为
OK
- 在其余行中,将列替换为
NG