다음과 같은 형식의 거대한 CSV 파일이 있습니다.
aaa1, "aaa2, aa214", aa21, "aa, a14", aa211, aa44, aaa445
data, data, data, data, data, data, data,
........................................
........................................
헤더에 특정 문자열(예: )이 포함된 열을 추출하고 싶습니다 a2
. 위의 예에서는 열 aaa2
등이 포함됩니다 aa21
.
내가 시도한 awk 명령은 다음과 같습니다.
awk --csv 'NR==1 {for (i=1; i<=NF; i++) if ($i ~ /a2/) print $i}' file.csv
그러나 이는 일치하는 헤더만 반환하고 그 아래 열은 반환하지 않습니다. 올바른 방향을 알려주세요. 저는 리눅스 시스템을 사용하고 있습니다.
답변1
mlr
이 가짜 CSV 형식은 실제로 지원되며 정규식을 기반으로 필드를 잘라낼 수 있습니다.
$ mlr --csv --csv-trim-leading-space --allow-ragged-csv-input cut -rf a2 your-file.csv
"aaa2, aa214",aa21,aa211
data,data,data
그러나 이는 메모리에 맞지 않는 CSV로 확장되지 않습니다. --allow-ragged-csv-input
예제와 행당 필드 수가 다른 CSV를 처리 하려면 어떤 경우에도 파일 전체를 읽어서 열 수를 파악해야 합니다(헤더가 없는 열에는 숫자 헤더가 자동으로 할당됨).
답변2
GNU awk를 사용 FPAT
하고 필드에 개행 문자가 포함되어 있지 않다고 가정합니다.
awk -v FPAT='[^,]*|\\s*("([^"]|"")*")\\s*' -v OFS=',' '
NR==1 {
for ( inFldNr=1; inFldNr<=NF; inFldNr++ ) {
if ( $inFldNr ~ /a2/ ) {
out2in[++numOutFlds] = inFldNr
}
}
}
{
for ( outFldNr=1; outFldNr<=numOutFlds; outFldNr++ ) {
inFldNr = out2in[outFldNr]
printf "%s%s", $inFldNr, (outFldNr<numOutFlds ? OFS : ORS)
}
}
' file.csv
"aaa2, aa214", aa21, aa211
data, data, data
--csv
입력 파일이 유효한 CSV가 아니기 때문에(GNU awk도 필요함) 사용하지 않았습니다 ( ,
s와 첫 번째 "
s 사이에 공백이 있고 ,
두 번째 줄 끝의 후행으로 인해 헤더보다 더 많은 데이터 열이 있음). CSV 파서가 이를 처리할 것으로 예상해서는 안 됩니다. 또한 이 문제를 해결하더라도 --csv
각 열 헤더 주위의 따옴표가 제거되므로 이를 유지하고 싶은 것 같습니다. 모든 필드가 큰따옴표로 묶이지 않은 경우 약간 문제가 됩니다. 필드에 개행 문자가 포함될 수 있고 어쨌든 필드 주변의 따옴표를 제거하려는 경우에는 --csv
올바른 설정을 사용하는 것보다 를 사용하는 것이 훨씬 더 좋습니다 .FPAT
정말로 시도해 보고 싶다면 --csv
다음(테스트되지 않음)이 도움이 될 수 있습니다.
awk --csv -v OFS=',' '
NR==1 {
for ( inFldNr=1; inFldNr<=NF; inFldNr++ ) {
if ( $inFldNr ~ /a2/ ) {
out2in[++numOutFlds] = inFldNr
}
}
}
{
for ( outFldNr=1; outFldNr<=numOutFlds; outFldNr++ ) {
inFldNr = out2in[outFldNr]
outVal = $inFldNr
if ( outVal ~ ("[" OFS ORS "\"]") ) {
gsub(/"/,"\"\"",outVal)
outVal = "\"" outVal "\""
}
printf "%s%s", outVal, (outFldNr<numOutFlds ? OFS : ORS)
}
}
' file.csv
"
그러나 루프에 s를 추가할 때 선행/후행 공백(있는 경우)이 처음에 따옴표 내부 또는 외부에 있었는지 알 수 있는 쉬운 방법이 없으므로 전체 필드를 인용했습니다.
바라보다awk를 사용하여 csv를 효율적으로 구문 분석하는 가장 강력한 방법은 무엇입니까CSV를 구문 분석하기 위해 awk를 사용하는 방법에 대한 추가 정보.
답변3
사용행복하다(이전 Perl_6)
...Raku의 Text::CSV
모듈을 사용하여:
~$ raku -MText::CSV -e 'csv(in => csv(in => $*IN, sep => ", "), out => $*OUT);' < file
위의 명령은 CSV 파일(모든 열)을 메모리로 읽습니다. 파일은 std-in을 통해 수신되고 모든 열은 $*IN
std-out을 통해 출력됩니다. $*OUT
사용자 정의 ", "
필드 구분 기호를 참고하세요.
특정 열을 필터링하려면(다른 모든 열 제거) 발견된 열의 숫자 인덱스를 반환하는 Raku의 grep
키 매개변수를 사용합니다.:k
~$ raku -MText::CSV -e 'my @aoa = csv(in => $*IN, sep => ", ");
my @col-nbrs = @aoa[0].grep(/a2/, :k);
for @aoa.map( *.[@col-nbrs]) {
.map(q["] ~ * ~ q["]).join("\t").put
};' < file
입력 예:
aaa1_a, "aaa2, aa214_b", aa21_c, "aa, a14_d", aa211_e, aa44_f, aaa445_g
data1_a, data1_b, data1_c, data1_d, data1_e, data1_f, data1_g,
data2_a, data2_b, data2_c, data2_d, data2_e, data2_f, data2_g,
출력 예(위의 TSV):
"aaa2, aa214_b" "aa21_c" "aa211_e"
"data1_b" "data1_c" "data1_e"
"data2_b" "data2_c" "data2_e"
위의 내용에는 "a2"와 일치하는 모든 열 이름이 포함되어 있습니다. 출력을 더 쉽게 읽을 수 있도록 각 필드의 텍스트를 따옴표로 묶은 다음 탭 join
에서 편집합니다 \t
. 따옴표가 없으면 코드가 훨씬 간단해집니다. 다음 열이 연결되어 \t\t
출력됩니다.
~$ raku -MText::CSV -e 'my @aoa = csv(in => $*IN, sep => ", ");
my @col-nbrs = @aoa[0].grep(/a2/, :k);
for @aoa.map( *.[@col-nbrs]) {
$_.join("\t\t").put
};' < file
aaa2, aa214_b aa21_c aa211_e
data1_b data1_c data1_e
data2_b data2_c data2_e
마지막으로 기본적으로 1. 열의 쉼표 , 2. 공백이 포함된 큰따옴표 필드와 Text::CSV
같은 출력 기능을 활용할 수 있습니다 .join
,
% raku -MText::CSV -e 'my @aoa = csv(in => $*IN, sep => ", ");
my @col-nbrs = @aoa[0].grep(/a2/, :k);
my @filtered; for @aoa.map( *.[@col-nbrs] ) {
@filtered.push($_);
}; csv(in => @filtered, out => $*OUT);' < file
"aaa2, aa214_b",aa21_c,aa211_e
data1_b,data1_c,data1_e
data2_b,data2_c,data2_e
https://raku.land/zef:Tux/Text::CSV
https://github.com/Tux/CSV/blob/master/doc/Text-CSV.md
https://docs.raku.org
https://raku.org
답변4
또 다른 매우 편리한 도구는오리 데이터베이스. 달리기
duckdb --csv -c "SELECT COLUMNS('.*a2.*') from read_csv_auto('input.csv',HEADER = true)" >output.csv
당신은 얻는다
AAA2,AAA214 | AA21 | AA211 |
---|---|---|
데이터 | 데이터 | 데이터 |
데이터 | 데이터 | 데이터 |