나는 입력 파일의 첫 번째 필드가 파일 이름인지 확인하고, 그렇지 않은 경우 파일 이름을 각 줄의 첫 번째 열로 추가하는 Perl 한 줄짜리 기능을 원합니다.
쉘로 작성된 예:
for f in *file*.csv;
do
file_column=`cat ${f} | awk -F',' '{print$1}'`
if [ $file_column != ${f} ]
then
sed -i "s/^/$f,/" $f 2>/dev/null;
fi
done
하지만 위의 방법은 첫 번째 열에 파일명이 있는지 확인하고, 없으면 추가하면 4 Laks 파일에 약 3시간이 소요됩니다. Perl이 파일 작업에 더 빠르다는 것을 알고 있습니다.
내가 시도한 Perl 명령은 다음과 같습니다.
perl -p -i -e 's/^/Welcome to Hell,/' file*.csv
필드가 이미 존재하는지 확인하고 존재하지 않는 경우에만 변경하는 논리를 추가하도록 도와주세요.
Input : file1.csv
col1,col2,col3
data1,data2,dat3
Output: file1.csv
file1.csv,col1,col2,col3
file1.csv,data1,data2,data3
아니면 더 빠른 방법이 있다면 제안해주세요. Perl 라이너는 다른 쉘 스크립트의 일부이므로 작은 호출이 더 좋을 것 같습니다(제안해 주세요).
답변1
이것은 Perl 라인입니다. 여러 파일 매개변수에 대해 작동합니다.
perl -i -pe '/^$ARGV,/ or print "$ARGV,"' file1 file2 ...
$ARGV
현재 파일의 파일 이름을 보유하는 마법 변수입니다.
보다http://perldoc.perl.org/perlvar.html#Variables-lated-to-filehandles
필드 구분 기호(쉼표)는 하드코드되어 있습니다. 이것이 문제인지 결정하는 것은 당신에게 달려 있습니다.
작은 성능 개선:
perl -i -pe 'index($_, "$ARGV,") == 0 or print "$ARGV,"' file1 file2 ...
답변2
Perl 속도에 대해 이야기하기 전에 스크립트 속도를 높여보십시오.
for f in *file*.csv;
do
sed -i "/^$f,/! s/^/$f,/" "$f"
done
답변3
실제로 Perl을 사용하여 이 작업을 수행할 수 있지만 구문은 가장 쉽지 않습니다(또는 적어도 제가 생각할 수 있는 최선은 아닙니다). 다른 도구를 사용하는 것이 더 쉽고 빠를 수도 있습니다. 예를 들어,
gawk (비교적 최신 버전)
for f in file*csv; do awk -i inplace -F, '{ if($1==FILENAME){print} else{print FILENAME","$0} }' "$f"; done
답변4
한 줄도 관리할 수 없지만 여기 한 줄이 있습니다진주스크립트. 파일에 넣어서 실행 가능하게 만드세요. 그런 다음 *.csv
파일 이름을 인수로 제공하십시오. 파일을 생성합니다 *.new
. 제대로 작동한다고 확신한다면
rename
마지막 명령의 주석 처리를 해제하세요.
#!/usr/bin/perl
use strict;
foreach my $file(@ARGV){
open(F,$file) or die "$file:$!";
$_ = <F>;
next if $_=~/^$file,/;
open(OUT,">$file.new") or die;
my $add = "$file,";
print OUT $add,$_;
while(<F>){
print OUT $add,$_;
}
close OUT;
close F;
#rename("$file.new","$file");
}