使用 awk 过滤字符串中的列,并通过 xargs 进行管道传输

使用 awk 过滤字符串中的列,并通过 xargs 进行管道传输

我有一些文件:

file1.csv
file2.csv
file3.csv

给定的脚本处理它们,并记录到此文件:

my.log

采用这种格式:( filename col2 col3):

file1.csv 1 a
file2.csv 1 a
file3.csv 1 a
file2.csv 2 b
file1.csv 2 b
file3.csv 2 b
file1.csv 3 c
file2.csv 3 c
file3.csv 3 c
file2.csv 4 d
file3.csv 4 d

我想从每个文件的文件中获取一个col3值(仅最后一个)。my.log*.csv

我运行这个命令:

ls *.csv | xargs -I@ bash -c "cat my.log | grep @ | tail -n 1 | awk '{ print $3 }'"

它工作得很好,除了 awk 给了我所有的列。

file1.csv 3 c
file2.csv 4 d
file3.csv 4 d

我怎样才能只得到col3一列?例如,这个:

c
d
d

答案1

在你的表情里

 "cat my.log | grep @ | tail -n 1 | awk '{ print $3 }'"

...该字符串周围的双引号意味着单引号被视为文字。它们不保护$3外壳,因此它被扩展为环境变量。由于$3实际上并未由 shell 定义(除非这是在您使用 3 个参数调用的脚本中),因此它变成空字符串,并且表达式awk很简单{ print },打印整行。

您可以通过转义来解决此问题$

ls *.csv | xargs -I@ bash -c "cat my.log | grep @|tail -n 1|awk '{print \$3}'"

...或者通过将表达式awk移出xargs

ls *.csv | xargs -I@ bash -c "cat my.log | grep @|tail -n 1"|awk '{print $3}'

答案2

ls将into的输出通过管道传输xargs是一个坏主意(事实上,对 into 的输出执行任何操作ls传输到是一个坏主意(事实上,除了简单地在终端中查看它之外,馊主意)。如果你绝对必须做这样的事情,至少使用类似的东西find . -maxdepth 1 -type f -iname '*.csv' -print0并将其通过管道传输到xargs -0r.

但是,在这种情况下,您根本不需要这样做,因为 .csv 文件的文件名是已经在my.log

在 awk 中:

#!/usr/bin/awk -f

{ seen[$1] = $3 }

END {
  for (f in seen) { print seen[f] };
}

或作为单行:

$ awk '{seen[$1] = $3}; END {for (f in seen) { print seen[f] };}' my.log 
c
d
d

这些将打印第 1 列中列出的每个文件在第 3 列中看到的最后一个值。

如果您希望它仅打印第 3 列中看到的第一个值,请将其更改为:

!seen[$1] { seen[$1] = $3 }

如果您不想使用find | xargs并且确实需要使用.csv当前目录中当前所有文件的文件名,一种替代方法是执行以下操作:

#!/usr/bin/perl

use strict;

my $logfile=shift;      # get the first arg (the logfile name)

my $re=join("|",@ARGV); # turn the remaining args into a regular expression

@ARGV=$logfile;         # set the logfile name as the sole cmd-line argument.

my %seen=();

while(<>) {
   next unless (m/^($re)/o); # ignore any filenames that weren't on the cmd line.
   my(@F) = split;
   $seen{$F[0]} = $F[2];  # perl arrays start from 0, not 1.
};

foreach my $file (sort keys %seen) {
  print $seen{$file}, "\n";
};

将其另存为,例如nandro.pl,使其可执行chmod +x并运行为:

$ ./nandro.pl my.log *.csv
c
d
d

相关内容