저는 쉼표로 구분된 모든 항목을 포함하는 대규모 csv 파일을 작업 중입니다. 전체 문서는 텍스트 형식의 통화를 반영하는 몇 가지 열을 제외하고 순전히 숫자로 구성됩니다. 예를 들어, 그러한 항목 중 하나는 유사하게 보일 수 "$12,345.67"
있고 다른 항목은 유사하게 보일 수 있습니다 "$1,234,567.89"
(큰따옴표 기호도 항목에 포함됨). 다음은 전체 데이터 레코드(1개 행)의 예입니다.
123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2
이 데이터 파일에 대해 일부 처리를 수행하고 싶기 때문에 해당 텍스트 필드를 순수한 숫자로 다시 포맷하고 싶습니다(예: 큰따옴표와 쉼표 제거). 정규식 패턴 대체가 나에게 효과적일 것이라고 생각 sed
하지만 정규식이 어떻게 생겼는지 전혀 모르겠습니다. 어떤 아이디어라도 크게 감사하겠습니다.
답변1
무엇을 해야 하는지 표현하는 것은 간단합니다.
"$
1 과 사이에 포함된 각 문자열에 대해 "
모두 삭제합니다 . ,
2 주변 "$
합계를 삭제합니다."
이것은 sed 표현입니다. 명령줄에서 사용하는 경우 적절하게 인용해야 합니다. command.sed라고 말하는 파일에 넣고 다음을 통해 호출하는 것이 더 간단합니다.
sed -f command.sed data.csv
다음은 이 두 단계를 달성하는 프로그램입니다.
:repeat
s/"\$\([^,"]*\),/"$\1/g
t repeat
s/"\$\([^"]*\)"/\1/g
이것문서문제를 해결하는 데 도움이되었습니다.
답변2
업데이트: 조정된 답변따옴표 사이의 공백만 바꾸기이 문제를 해결하기 위해.
주문하다:
echo '123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2' |
awk -F\" '{OFS="\""; for (i = 2; i < NF; i += 2) gsub(/[$,]/,"",$i); gsub(/"/,""); print}'
산출:
123,7,11,343700.14,34928.63,377000.00,15421.92,19,2
첫 번째는 gsub
큰따옴표 안에 있는 $
s와 s를 제거합니다. ,
두 번째는 따옴표 자체를 제거합니다.
도움이 될 경우를 대비해 원래 답변을 아래에 남겨주세요.
내가 올바르게 이해했다면 간단한 검색 및 바꾸기로 문제를 해결할 수 있습니다.
echo '"$1,234,567.89"' | sed 's/[$,"]//g'
출력 1234567.89
.
이 플래그는 ( )와 일치하는 ( ) 문자를 대체 s
하고 아무것도 대체하지 않습니다(마지막 두 개는 그 사이에 비어 있음). 이 플래그를 사용하면 모든 인스턴스를 대체하여 전역적으로 적용할 수 있습니다(그렇지 않으면 줄의 첫 번째 인스턴스만 대체됩니다).[]
$
,
"
/
g
전체 파일에 적용되는 방식은 파일 형식에 따라 다릅니다. 파일에 큰따옴표, 달러 기호 및 쉼표가 포함되어 있지 않으면 문제가 없습니다.
sed 's/[$,"]//g' /path/to/file
답변3
이 통화 값이 표시되는 방식은 CSV 뷰어에 따라 다릅니다. 이 필드를 변경하는 대신 Excel에서 보기를 변경하는 것이 어떻습니까?
어쨌든 csv에 여러 필드가 있을 수 있으므로 다음과 같은 처리기 스크립트를 사용하는 것이 더 안전합니다.
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;
my $csv = Text::CSV->new ( { binary => 1 } );
while ( my $row = $csv->getline(\*STDIN) ) {
foreach my $item (@$row)
{
$item =~ s/,//g if ($item =~ /^\$[0-9,.]+$/);
}
$csv->print (\*STDOUT, $row);
print "\n";
}
사용법: ./csv.pl < in.csv > ou.csv
입력하다:
abc,"$1,243,311.99",def
abc2,"$43,311.99",def2
산출:
abc,$1243311.99,def
abc2,$43311.99,def2
답변4
약간 더 복잡한 awk 솔루션은 다음을 기반으로 합니다.awk를 사용하여 CSV 구문 분석
{
$0=$0","; # yes, cheating
while($0) {
gsub(/\$/,"",$0)
match($0,/ *"[^"]*" *,|[^,]*,/);
sf=f=substr($0,RSTART,RLENGTH); # save what matched in sf
gsub(/^ *"?|"? *,$/,"",f); # remove extra stuff
gsub(/,/,"",f);
if($0 ~ /,[^,]+,$/){
printf "%s,",f;
}else{
printf "%s",f;
}
sub(sf,""); # "consume" what matched
}
printf "\n"
}
위 내용을 csv.awk로 저장하고 다음과 같이 실행합니다.
echo '123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2'|awk -f csv.awk
123,7,11,343700.14,34928.63,377000.00,15421.92,19,2