【问题标题】:manipulating files using awk linux使用 awk linux 操作文件
【发布时间】:2018-03-05 08:19:15
【问题描述】:

我有一个 1.txt 文件(字段分隔符为||o||):

aidagolf6@gmail.com||o||bb1e6b92d60454122037f302359d8a53||o||Aida||o||Aida||o||Muji?
aidagolf6@gmail.com||o||bcfddb5d06bd02b206ac7f9033f34677||o||Aida||o||Aida||o||Muji?
aidagolf6@gmail.com||o||bf6265003ae067b19b88fa4359d5c392||o||Aida||o||Aida||o||Garic Gara
aidagolf6@gmail.com||o||d3a6a8b1ed3640188e985f8a1efbfe22||o||Aida||o||Aida||o||Muji?
aidagolfa@hotmail.com||o||14f87ec1e760d16c0380c74ec7678b04||o||Aida||o||Aida||o||Rodriguez Puerto

2.txt(字段分隔符为:):

bf6265003ae067b19b88fa4359d5c392:hyworebu:@
14f87ec1e760d16c0380c74ec7678b04:sujycugu

我有一个 result.txt 文件(它将 1.txt 的第二列与 2.txt 的第一列匹配,如果结果匹配,它将用 2.txt 的第二列替换 1.txt 的第二列)

aidagolf6@gmail.com||o||hyworebu:@||o||Aida||o||Aida||o||Garic Gara
aidagolfa@hotmail.com||o||sujycugu||o||Aida||o||Aida||o||Rodriguez Puerto

还有一个 left.txt 文件(其中包含来自 1.txt 且在 2.txt 中没有匹配的不匹配行):

aidagolf6@gmail.com||o||d3a6a8b1ed3640188e985f8a1efbfe22||o||Aida||o||Aida||o||Muji?
aidagolf6@gmail.com||o||bb1e6b92d60454122037f302359d8a53||o||Aida||o||Aida||o||Muji?
aidagolf6@gmail.com||o||bcfddb5d06bd02b206ac7f9033f34677||o||Aida||o||Aida||o||Muji?

我正在尝试的脚本是:

awk -F '[|][|]o[|][|]' -v s1="||o||"  '
NR==FNR {
a[$2] = $1; 
b[$2]= $3s1$4s1$5; 
next
} 
($1 in a){
$1 = "";
sub(/:/, "")
print a[$1]s1$2s1b[$1] > "result.txt";
next
}' 1.txt 2.txt

问题是脚本在 2.txt 中使用 ||o|| 也是因为我得到了错误的结果。

编辑

修改后的脚本:

awk -v s1="||o||"  '
NR==FNR {
a[$2] = $1; 
b[$2]= $3s1$4s1$5; 
next
} 
($1 in a){
$1 = "";
sub(/:/, "")
print a[$1]s1$2s1b[$1] > "result.txt";
next
}' FS = "||o||" 1.txt FS = ":" 2.txt

现在,我收到以下错误:

awk:致命:无法打开文件“FS”进行读取(没有这样的文件或 目录)

【问题讨论】:

  • 我建议学习Python
  • 我已经知道python了。但我需要的解决方案是 bash。感谢您的帮助:)
  • 你可以从 bash 调用 python,就像你从 bash 调用 awk。
  • 是谁发明了这个规范的定界符?更重要的是为什么?
  • 您可以为不同的文件设置不同的 FS,请参阅:stackoverflow.com/questions/24516141/… .. 可能这符合重复的条件?

标签: linux bash awk


【解决方案1】:

我修改了你原来的脚本:

awk -F'[|][|]o[|][|]' -v s1="||o||" '

NR == FNR {
    a[$2] = $1; 
    b[$2] = $3 s1 $4 s1 $5;
    c[$2] = $0;                     # keep the line for left.txt
}

NR != FNR {
    split($0, d, ":");
    r = substr($0, index($0, ":") + 1);     # right side of the 1st ":"
    if (a[d[1]] != "") {
        print a[d[1]] s1 r s1 b[d[1]] > "result.txt";
            c[d[1]] = "";           # drop from the list of left.txt
    }
}

END {
    for (var in c) {
        if (c[var] != "") {
            print c[var] > "left.txt"
        }
    }
}' 1.txt 2.txt

下一个版本更改文件读取顺序以减少内存消耗:

awk -F'[|][|]o[|][|]' -v s1="||o||" '

NR == FNR {
    split($0, a, ":");
        r = substr($0, index($0, ":") + 1); # right side of the 1st ":"
    map[a[1]] = r; 
}

NR != FNR {
    if (map[$2] != "") {
        print $1 s1 map[$2] s1 $3 s1 $4 s1 $5 > "result.txt";
    } else {
        print $0 > "left.txt"
    }
}' 2.txt 1.txt

最终版本使用基于文件的数据库,最大限度地减少 DRAM 消耗,尽管我不确定 Perl 在您的系统中是否可以接受。

perl -e '
use DB_File;

$file1 = "1.txt";
$file2 = "2.txt";
$result = "result.txt";
$left = "left.txt";

my $dbfile = "tmp.db";
tie(%db, "DB_File", $dbfile, O_CREAT|O_RDWR, 0644) or die "$dbfile: $!";

open(FH, $file2) or die "$file2: $!";
while (<FH>) {
    chop;
    @_ = split(/:/, $_, 2);
    $db{$_[0]} = $_[1];
}
close FH;
open(FH, $file1) or die "$file1: $!";
open(RESULT, "> $result") or die "$result: $!";
open(LEFT, "> $left") or die "$left: $!";

while (<FH>) {
    @_ = split(/\|\|o\|\|/, $_);
    if (defined $db{$_[1]}) {
        $_[1] = $db{$_[1]};
        print RESULT join("||o||", @_);
    } else {
        print LEFT $_;
    }
}
close FH;
untie %db;
'
rm tmp.db

【讨论】:

  • 它适用于较小的数据。让我测试更大的文件。到时候我会赞成的。感谢您的帮助。
  • 对于更大的文件,我在 result.txt 中得到的行数比 1.txt 多
  • 你能给我看看重现该现象的示例文件吗?
  • 它们是非常大的文件,一个是 13 GB,另一个是 3 GB。
  • 呃,哦,尺寸比我预期的要大得多。到目前为止,我无法想象故障的原因,但将字符串保存在关联数组中可能不是一个好主意。让我睡吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多