2

次の形式の 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

私が達成しようとしているのは、最初の 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 内の複数のファイルにアクセスする方法がわかりません。それが最善の方法であるかどうかもわかりません。ファイルが大きいので何度も繰り返すことになるので、毎回マッピングをチェックするのは正しい方法ではないと思います。

マップをシェル スクリプト内のハッシュ テーブルに格納し、ハッシュ マッピングを使用して置き換える方法はありますか?

4

4 に答える 4

3

1 つの純粋な 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

マップ ファイルのキーが負でない整数の場合、連想配列は必要なく、行declare -A map=()map=().

Bash はデータを処理するのに最速ではないため、最も効率的ではないかもしれませんが、うまく機能します!

ところで、エラー チェックはまったく行われないため、このスクリプトは適切な形式のファイルに適用してください。

あなたの例では、これにより次の結果が得られます。

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
于 2013-11-05T09:40:04.233 に答える
3

パールソリューション。最近のバージョンの 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;
}
于 2013-11-05T09:42:35.980 に答える
1

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
于 2013-11-05T10:53:57.223 に答える