いくつかのファイルがあります。
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
列を1つだけ取得するにはどうすればよいですかcol3
?たとえば、次のようになります。
c
d
d
答え1
あなたの表現に
"cat my.log | grep @ | tail -n 1 | awk '{ print $3 }'"
...文字列の周囲の二重引用符は、一重引用符がリテラルとして処理されることを意味します。シェルを保護しないので、$3
環境変数に展開されます。実際にはシェルによって定義されていないので$3
(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
。
まったく:
#!/usr/bin/awk -f
{ seen[$1] = $3 }
END {
for (f in seen) { print seen[f] };
}
または1行で:
$ 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