Bash 如何用另一个文件中的映射值替换csv文件中的第n个字段?

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

我有以下格式的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: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
。这样很好<代码>:)
。像符咒一样工作:-)