Bash 如何用另一个文件中的映射值替换csv文件中的第n个字段?
我有以下格式的csv文件:Bash 如何用另一个文件中的映射值替换csv文件中的第n个字段?,bash,csv,sed,awk,Bash,Csv,Sed,Awk,我有以下格式的csv文件: 23:56:00,5,1,7,99,100,101 23:56:30,5,1,7,98,199,191 23:57:00,6,1,6,99,99,98 23:57:30,5,2,6,97,99,199 ... 1:10 2:12 3:30 4:aa 5:16 6:11 7:bb 以及以下格式的地图文件: 23:56:00,5,1,7,99,100,101 23:56:30,5,1,7,98,199,191 23:57:00,6,1,6,99,99,98 23:57
23:56:00,5,1,7,99,100,101
23:56:30,5,1,7,98,199,191
23:57:00,6,1,6,99,99,98
23:57:30,5,2,6,97,99,199
...
1:10
2:12
3:30
4:aa
5:16
6:11
7:bb
以及以下格式的地图文件:
23:56:00,5,1,7,99,100,101
23:56:30,5,1,7,98,199,191
23:57:00,6,1,6,99,99,98
23:57:30,5,2,6,97,99,199
...
1:10
2:12
3:30
4:aa
5:16
6:11
7:bb
我试图完成的是用映射文件中的值替换第一个csv文件中第2、3和4列中的字段
例如,在上述情况下,我想要的最终输出是:
23:56:00,16,10,bb,99,100,101
23:56:30,16,10,bb,98,199,191
23:57:00,11,10,11,99,99,98
23:57:30,16,12,11,97,99,199
最好的方法是什么?我试图找到一种使用awk/sed的方法,但我不确定如何访问awk中的多个文件,以及这是否是最好的方法。因为它是一个大文件,所以会有很多重复,所以我不认为每次都检查映射是正确的方法
有没有办法将映射存储到shell脚本内的哈希表中,然后使用哈希映射替换 试试:
awk '
BEGIN { FS = OFS = "," }
FNR == NR {
split($0, f, /:/)
map[f[1]] = f[2]
next
}
{
for (i=2; i<=4; i++) {
if ($i in map) { $i = map[$i] }
}
}
{ print }
' mapfile csvfile
一种纯Bash的可能性(使用Bash版本)≥4) :
在关联数组中滑动贴图文件并处理csv文件:
#!/bin/bash
declare -A map=()
while IFS=: read -r k v; do
[[ -z "$k$v" ]] && continue # ignore empty lines
map[$k]=$v
done < mapfile.txt
IFS=,
while read -r -a ary; do
[[ -z "${ary[@]}" ]] && continue # ignore empty lines
ary[1]=${map[${ary[1]}]}
ary[2]=${map[${ary[2]}]}
ary[3]=${map[${ary[3]}]}
echo "${ary[*]}"
done < csvfile.txt
Perl解决方案。哈希存在于bash的最新版本中,但我更喜欢使用真正的编程语言
#!/usr/bin/perl
use warnings;
use strict;
open my $MAP, '<', '1.map' or die $!;
my %map;
while (<$MAP>) {
chomp;
my ($key, $value) = split /:/;
$map{$key} = $value;
}
open my $CSV, '<', '1.csv' or die $!;
while (<$CSV>) {
my @fields = split /,/;
s/(.*)/$map{$1}/ for @fields[1, 2, 3];
print join ',' => @fields;
}
#/usr/bin/perl
使用警告;
严格使用;
打开我的$MAP,“另一个awk
awk -F",|:" 'FNR==NR {a[$1]=$2;next} {print $1":"$2":"$3,a[$4],a[$5],a[$6],$7,$8,$9}' OFS=, map csv
23:56:00,16,10,bb,99,100,101
23:56:30,16,10,bb,98,199,191
23:57:00,11,10,11,99,99,98
23:57:30,16,12,11,97,99,199
你的方法很有效,只需一个命令就可以找到Bur awk(查看Birei的答案)@Ashish我知道!但这个问题将有一套全面的答案:awk
,Bash
,Perl
。这样很好<代码>:)
。像符咒一样工作:-)