큰 따옴표 안에있는 쉼표 만 제거하십시오.


10

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

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이것에 대한 해결책을 게시하면 기쁩니다 .


에서 56,72,"12,34,54",x,y,"foo,a,b,bar"56,72,123454,x,y,"a,b", foo그리고 barIS가 사라집니다. 원하는 출력입니까?
cuonglm

쉼표와 함께 일부 요소 ( foo및 등 bar)가 제거 되므로 사용하는 예제가 약간 혼동 됩니다. 또한 일부 인용문은 다른 인용문에서 사라집니다. 쉼표 사이에 a있으며 쉼표도 b그대로 남아 있습니다. 이것들에 어떤 패턴이 있습니까?
HalosGhost

죄송합니다 친구를 수정했습니다.
Avinash Raj

편집 한 내용이 실제로 명확하게 설명되지 않았습니다. 내 마지막 의견을 참조하십시오 .
HalosGhost

큰 따옴표 안의 쉼표와 따옴표에 숫자가 포함 된 경우에만 따옴표를 제거하십시오.
Avinash Raj

답변:


7

@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)), \1될 것입니다 foobar\2있을 것입니다 bar.
    • "[0-9,]*",?: 0 일치 이상 0-9또는 ,0 또는 1 다음에 ,.
    • ("[0-9,]*",?)* : 위의 0 이상과 일치합니다.
    • "[0-9,]*: 0 일치 이상 0-9또는 ,직후에 와서 그"
  • 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과 같은 프로그래밍을하는 것이 더 나을 것입니다.


10

perl이 정상이라면, 여기에 짧은 (그리고 아마도 간단하지는 않지만 빠를 수도 있습니다) 방법이 있습니다 :

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

연산자에 대한 e플래그 s:::(쓰기의 또 다른 방법 임 s///)는 대체가 매번 평가되는 표현식으로 처리되도록합니다. 그 표현은 소요 $1((이미 따옴표가 누락)와 변환 정규식에서 캡처 y///도 같이 쓸 수있는 tr///)을 (삭제하여 /d쉼표 모두). r에 플래그는 y대신 번역의 수의 값은 번역 된 문자열로 얻기 위해 필요하다.

어떻게 든 펄에 의해 괴로워한다고 느끼는 사람들을 위해, 여기에 파이썬과 동등한 것이 있습니다. 파이썬은 실제로 쉘 한 줄짜리 도구가 아니지만 때로는 협력으로 연결될 수 있습니다. 다음은 한 줄로 작성할 수 있지만 ( 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

@rici : 좋은 하나! 그리고 하나 더 문자 y///tr///저장 하는 대신 사용 하십시오.
cuonglm

6

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"

0

인용구

안녕하세요 쉼표를 큰 따옴표로 바꾸는 Python 코드 는 다음과 같습니다 . 쉼표는 파이프 (|) 문자로 바뀝니다.

이 파이썬 코드는 큰 따옴표로 묶은 쉼표를 대체하는 것입니다

예 : x, y, z, 1,2, "r, e, t, y", h, 8,5,6

파이프 x, y, z, 1,2, "r | e | t | y", h, 8,5,6으로 교체하는 경우

null x, y, z, 1,2, "rety", h, 8,5,6으로 교체하는 경우

writingFile = open('FileToWrite', 'w')
with open('FileToRead') as f:

    while True:

        c = f.read(1)
        if not c:
            print ("End of file")
            break
        print ("Read a character:", c)


        if c=='"':
            writingFile.write(c) 
            c = f.read(1)
            while c != '"':
                if c== ',':
                    c= '|'
                writingFile.write(c)
                c = f.read(1)


        writingFile.write(c)


writingFile.close()

약간의 설명이 필요했습니다.
Mongrel

이 파이썬 코드는 큰 따옴표로 대체하기 위해 사용됩니다
Vijay Kumar Akarapu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.