CSV 파일에서 큰따옴표로 묶인 숫자에 있는 쉼표만 제거합니다.

CSV 파일에서 큰따옴표로 묶인 숫자에 있는 쉼표만 제거합니다.

,텍스트 파일에서 (쉼표)와 (따옴표)를 제거하고 싶습니다 "(큰따옴표에 쉼표로 구분된 숫자가 포함된 경우에만).

56,72,"12,34,54",x,y,"foo,a,b,bar"

예상 출력

56,72,123454,x,y,"foo,a,b,bar"

노트:위의 줄은 예시로만 사용됩니다. 내 텍스트 파일에는 위와 같은 많은 줄이 포함되어 있습니다. 큰따옴표 안의 쉼표로 구분된 숫자는 달라야 합니다. 그건,

56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"

예상 출력:

56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

큰따옴표 안에는 쉼표로 구분된 많은 숫자가 있습니다 n. 그리고 문자가 포함된 큰따옴표를 유지하세요.

나는 sed텍스트 처리 도구를 좋아합니다. sed이에 대한 해결책을 게시해 주시면 기쁠 것입니다.

답변1

Perl이 괜찮다면 여기에 짧은(반드시 간단하지는 않지만 아마도 빠를 것입니다 :)) 방법이 있습니다:

perl -pe 's:"(\d[\d,]+)":$1=~y/,//dr:eg' file

e연산자의 플래그( s:::작성하는 또 다른 방법 s///)는 대체가 매번 평가되는 표현식으로 처리되도록 합니다. 이 표현식은 $1정규 표현식(이미 따옴표가 누락됨)에서 캡처를 가져와 모든 쉼표( y///, 로 쓸 수도 있음)를 제거( )하여 변환합니다. (번역 횟수 대신) 번역된 문자열의 값을 얻으려면 to 플래그를 사용해야 합니다.tr////dry

Perl에 오염되었다고 느끼는 사람들을 위해 Python과 동등한 것이 있습니다. Python은 실제로 쉘 한 줄이 아니지만 때로는 협력하도록 유도될 수 있습니다. 다음은 한 줄로 작성할 수 있지만( for할 수 없는 루프와는 달리) 가로 스크롤을 사용하면 읽기가 (더욱) 어려워집니다.

python -c '
import re;
import sys;
r=re.compile("\"(\d+(,\d+)*)\"");
all(not sys.stdout.write(r.sub(lambda m:m.group(1).replace(",",""),l))
    for l in sys.stdin)
' < file

답변2

이 (에서 적응여기) 필요한 작업을 수행해야 하지만 @rici의 Perl이 더 간단합니다.

$ sed -r ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;ta; s/""/","/g; 
          s/"([0-9]*)",?/\1,/g ' file
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454,
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

설명하다

  • :a: 라는 레이블을 정의합니다 a.
  • s/(("[0-9,]*",?)*"[0-9,]*),/\1/: 이건 분해해야 해
    • 먼저 다음 구조를 사용하세요: (foo(bar)), \1will be foobar\2will be bar.
    • "[0-9,]*",?: 0개 이상의 0-9or와 일치하고 ,그 뒤에 0 또는 1이 옵니다 ,.
    • ("[0-9,]*",?)*: 위 항목 중 0개 이상 일치합니다.
    • "[0-9,]*0-9: 0 이상 또는 다음과 일치합니다.,"
  • ta;: 레이블로 돌아가서 a다시 실행만약에교체에 성공했습니다.
  • s/""/","/g;: 후처리. ""사용. . . 교체 ",".
  • s/"([0-9]*)",?/\1,/g: 숫자 주위의 모든 따옴표를 제거합니다.

다른 예를 들면 이해하기가 더 쉬울 수도 있습니다.

$ echo '"1,2,3,4"' | sed -nr ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;p;ta;'
"1,2,34"
"1,234"
"1234"
"1234"

따라서 쉼표와 다른 숫자가 뒤따르는 따옴표 바로 뒤의 숫자를 찾을 수 있지만 두 숫자를 연결하고 더 이상 불가능할 때까지 프로세스를 반복하십시오.

이 시점에서 나는 info sed위에 사용된 태그와 같은 고급 기능을 설명하는 섹션에 나타나는 인용문을 언급하는 것이 유용할 것이라고 생각했습니다(@Braiam을 찾아주셔서 감사합니다).

대부분의 경우 이러한 명령을 사용하면 "awk" 또는 Perl과 같은 언어로 프로그래밍하는 것이 더 좋습니다.

답변3

CSV 데이터의 경우 실제 CSV 파서가 있는 언어를 사용합니다. Ruby를 예로 들어보겠습니다.

ruby -rcsv -pe '
  row = CSV::parse_line($_).map {|e| e.delete!(",") if e =~ /^[\d,]+$/; e} 
  $_  = CSV::generate_line(row)
' <<END
56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"
END
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

답변4

사용행복하다(이전 Perl_6)

~$ raku -pe 's:g/ \" ~ \" (\d+) ** 2..* % "," /{$0.join}/;'  file

입력 예:

56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"

예제 출력:

56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"

Raku는 강력한 정규식 기능을 많이 갖춘 Perl 제품군의 프로그래밍 언어입니다. 이 답변에 대한 일반적인 개요는 아래 URL을 참조하세요.

https://unix.stackexchange.com/a/722570/227738

위 코드에서는 숫자가 인식되고 삽입된 쉼표가 제거되었습니다. 정규식은 다음 사실을 활용합니다.중첩된 구조\" ~ \" [\d+]이는 ""큰따옴표"로 둘러싸인 하나 이상의 숫자"를 의미하는 Raku의 새로운 ~ 물결표(중첩) 표기법을 사용하여 표현할 수 있습니다 .

또한,반복 구조%Raku의 새로운 변형 반복구조 수량자를 사용하여 표현할 수 있습니다. 표기법 [\d+] ** 2..* % ","는 " ,쉼표로 구분된 하나 이상의 숫자를 의미합니다. 이 패턴은 ** 2..*두 번 이상 반복됩니다. [후행 구분 기호(예: 쉼표)가 있는 경우, 구문에서 %%] 대신 a를 사용하십시오.%

이것은 시작에 불과합니다. 대체 구분 기호, 삽입된 줄 바꿈, 삽입된 쉼표, 빈 필드 등이 포함된 CSV 파일은 실제로 Text::CSV실제 CSV 파서(예: Raku 모듈)로 처리해야 합니다. 자세한 내용은 아래 링크를 참조하세요.

https://docs.raku.org/언어/regexes
https://raku.land/github:Tux/Text::CSV
https://raku.org

관련 정보