CSV 파일의 하위 문자열을 특정 길이로 자릅니다.

CSV 파일의 하위 문자열을 특정 길이로 자릅니다.

아래와 같은 파일이 있습니다.Test.csv

"pav",12345,"ABCD,EF;xyz23;15rtg",,
"xyz",,"C4DEF;x23yu;rtg",,

수정 후:

cat Test.csv

"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,

이것""로 구분된 하위 문자열을 포함하는 rd 필드는 ;해당 하위 문자열로 대체되어야 합니다.

답변1

다음이 사용됩니다csvkit참조 필드에 쉼표가 포함된 CSV 데이터를 직접 구문 분석하면 awk오류가 발생하기 쉽기 때문입니다.

그러면 올바른 형식의 세 번째 열이 생성됩니다.

csvcut -c 3 file.csv |
sed -r 's/^"|"$//g' |
awk -F';' -vOFS=';' '{ for (i=1; i<=NF; ++i) $i = substr($i, 0, 2) } { printf("\"%s\"\n", $0) }' >tmp-3rd

주어진 입력에 대해 이는 다음을 생성합니다.

"AB;xy;15"
"C4;x2;rt"
  • csvcut세 번째 열이 잘립니다.
  • sed모든 큰따옴표가 줄의 첫 번째나 마지막에 나타나면 데이터에서 제거됩니다.
  • 프로그램 은 -구분된 필드를 awk반복하여 ;필드당 2자 길이로 줄입니다. 큰따옴표로 데이터를 인쇄합니다.
  • 출력은 파일에 기록됩니다 tmp-3rd.

그런 다음 원래 데이터로 다시 조립하십시오(이는 bash절차적 대체를 수행하는 데 사용할 수 있는 다른 쉘이라고 가정합니다 <(...)).

paste -d, <( csvcut -c 1,2 file.csv ) tmp-3rd <( csvcut -c 4,5 file.csv ) | csvformat
  • paste열은 쉼표로 구분되어 함께 그룹화됩니다.
  • 첫 번째 프로세스는 원본 파일의 처음 두 열을 대체하고 두 번째 프로세스는 마지막 두 열을 대체합니다. 중간에는 수정된 세 번째 열을 제공합니다.
  • csvformat선택적인 단계로 필요에 따라 필드를 참조하거나 역참조하여 데이터를 전달합니다 .

출력은 다음과 같습니다

pav,12345,AB;xy;15,,
xyz,,C4;x2;rt,,

임시 파일의 필요성을 우회합니다.

paste -d, \
    <( csvcut -c 1,2 file.csv ) \
    <( csvcut -c 3 file.csv | sed -r 's/^"|"$//g' |
       awk -F';' -vOFS=';' '{ for (i=1; i<=NF; ++i) $i = substr($i, 0, 2) } { printf("\"%s\"\n", $0) }' ) \
    <( csvcut -c 4,5 file.csv ) | csvformat

답변2

그리고perl

;세 번째 필드에서만 가정

$ perl -pe 's/"\K[^;"]*;[^"]*(?=")/$&=~s|([^;]{2})[^;]+|$1|gr/e' ip.txt
"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,
  • "\K"관심 문자열 앞과 관심 문자열 뒤에서 일치합니다 (?="). "그러나 "이는 예측 문자열이므로 캡처 문자열 자체의 일부가 아닙니다.
  • [^;"]*;[^"]*;-OR 이 아닌 "문자 뒤에 문자가 ;아닌 "문자가 오는 것과 일치합니다.
  • $&=~s|([^;]{2})[^;]+|$1|gr일치하는 문자열에 대해 또 다른 교체를 수행합니다.
  • eModifier를 사용하면 교체 부품에 Perl 코드를 사용할 수 있습니다.


세 번째 필드만 제한

$ cat ip.txt 
"pav",12345,"ABCD,EF;xyz23;15rtg",,
"xyz",,"C4DEF;x23yu;rtg",,
"foo;12,23;good",124,253
12,5232,"xyz","ijk;5545;62"

$ perl -pe 's/^("[^"]*",|[^,]*,){2}"\K[^;"]*;[^"]*(?=")/$&=~s|([^;]{2})[^;]+|$1|gr/e' ip.txt
"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,
"foo;12,23;good",124,253
12,5232,"xyz","ijk;5545;62"

답변3

정확하고 견고함파이썬3.x 솔루션(기반csv.reader목적):

parse_csv.py스크립트:

import csv, sys
with open(sys.argv[1]) as f:
    reader = csv.reader(f)
    for l in reader:
        l = [s if ';' not in s else ';'.join(_[:2] for _ in s.split(';')) for s in l]
        print(','.join(i if not i or i.isnumeric() else '"{}"'.format(i) for i in l))

용법:

python3 parse_csv.py Test.csv

산출:

"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,

Python의 모듈은 csv데이터에 대한 강력하고 유연한 지원을 제공합니다.csv

답변4

복잡한 GNUAWK솔루션( csv데이터 구문 분석):

awk -v FPAT='"[^"]+"|[^",]+|,,' '{ 
           for (i=1;i<=NF;i++) { 
               if ($i~/^".*;./) { 
                   len=split($i,a,";"); v=substr(a[1],1,3); 
                   for (j=2;j<=len;j++) v= v";"substr(a[j],1,2);
                   v=v"\042"
               }  printf "%s%s",(v? v: ($i~/^,,/? (i==NF? ",":""):$i )),
                                (i==NF? ORS:OFS); v="" 
           } 
       }' OFS=',' Test.csv
  • FPAT='"[^"]+"|[^",]+|,,'- 필드 값에 대한 복잡한 정규식 패턴 정의

  • if ($i~/^".*;./) ...- 현재 필드에 문자가 $i포함되어 있는 경우;

  • len=split($i,a,";")- 필드 값을 $i구분 기호로 배열로 분할합니다. 생성된 요소/블록의 개수가 할당됩니다.a;len

  • v=substr(a[1],1,3);- 선행 문자를 포함하여 필요한 길이의 첫 번째 블록을 캡처합니다 ". "AB에서 추출됩니다"ABCD,EF

  • for (j=2;j<=len;j++) ...- 남은 청크/항목을 반복합니다.

  • v=v"\042"- "처리된 시퀀스에 후행 큰따옴표를 추가합니다 v. \043큰따옴표로 묶인 char 을 나타내는 ASCII 8진수 코드입니다 ".

  • ($i~/^,,/? (i==NF? ",":""):$i )- 각각의 빈 필드는 단일 쉼표와 공통 구분 기호를 사용하여 ,,다시 생성됩니다 . 이는 불필요한 쉼표 혼란을 피하기 위한 것입니다.,,"pav",,,

  • (i==NF? ORS:OFS)- 마지막 필드가 발견되면 i==NF- 레코드 구분자를 인쇄하고 ORS, 그렇지 않으면 - 필드 구분자를 인쇄합니다.OFS


산출:

"pav",12345,"AB;xy;15",,
"xyz",,"C4;x2;rt",,

관련 정보