쉼표로 구분된 파일에서 따옴표 안에 포함된 쉼표만 제거합니다.

쉼표로 구분된 파일에서 따옴표 안에 포함된 쉼표만 제거합니다.

쉼표()로 구분된 입력 파일이 있습니다 ,. 일부 필드는 쉼표와 함께 큰따옴표로 묶여 있습니다. 샘플라인입니다

123,"ABC, DEV 23",345,534.202,NAME

큰따옴표뿐만 아니라 큰따옴표 안에 있는 모든 쉼표를 제거해야 합니다. 따라서 위 줄은 다음과 같이 구문 분석되어야 합니다.

123,ABC DEV 23,345,534.202,NAME

다음 사용법을 시도했지만 sed예상한 결과를 얻지 못했습니다.

sed -e 's/\(".*\),\(".*\)/\1 \2/g'

sed아니면 awk다른 UNIX 유틸리티에 대한 빠른 팁이 있습니까?

답변1

awk인용문이 균형을 이루면 다음과 같이 표현될 수 있는 인용문 사이의 쉼표를 제거해야 합니다.

awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "", $i) } 1' infile

산출:

123,ABC DEV 23,345,534.202,NAME

설명하다

큰 따옴표 문자로 필드 분할을 수행하도록 awk에 지시합니다 -F". 이는 다른 모든 필드가 따옴표로 묶인 텍스트임을 의미합니다. for 루프는 gsub다른 모든 필드에서 작동합니다. 전역 대체의 약자로서 ","쉼표( )를 빈( "")으로 바꿉니다. 마지막으로 1기본 코드 블록을 호출합니다: { print $0 }.

답변2

하나 있다좋아요응답, sed를 한 번만 사용하세요반지:

echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME'|
  sed ':a;s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /;ta'
123,"ABC  DEV 23",345,534,"some more  comma-separated  words",202,NAME

설명하다:

  • :a;추가 지점에 대한 레이블입니다.
  • s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /3개의 닫힌 부품을 포함할 수 있습니다.
    • 첫 번째 두 번째: [^"]*,\?\|"[^",]*",\?큰따옴표를 포함하지 않고 뒤에 쉼표가 올 수도 있는 문자열과 일치합니다.또는쉼표 없이 두 개의 큰따옴표로 묶인 문자열이며 뒤에 쉼표가 올 수도 있습니다.
    • 첫 번째 것보다희토류 부분이전에 설명한 파트 2의 여러 반복으로 구성되며 그 뒤에 큰따옴표와 일부 문자가 따르지만 큰따옴표와 쉼표는 없습니다.
    • 첫 번째 RE 부분 뒤에는 혼수상태가 옵니다.
    • 나머지 줄은 건드릴 필요가 없습니다.
  • ta:a이전 s/명령이 일부 변경된 경우 반복됩니다.

루프가 완료되면 다음을 추가할 수도 있습니다 s/ */ /g.

echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME'|
    sed ':a;s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /;ta;s/  */ /g'

이중 공백을 억제합니다.

123,"ABC DEV 23",345,534,"some more comma-separated words",202,NAME

답변3

균형 잡힌 따옴표 사이의 여러 쉼표도 처리하는 일반적인 솔루션에는 중첩된 대체가 필요합니다. 나는 주어진 입력의 각 줄을 처리하고 다른 모든 따옴표 쌍의 쉼표만 바꾸는 솔루션을 Perl로 구현했습니다.

perl -pe 's/ "  (.+?  [^\\])  "               # find all non escaped 
                                              # quoting pairs
                                              # in a non-greedy way

           / ($ret = $1) =~ (s#,##g);         # remove all commas within quotes
             $ret                             # substitute the substitution :)
           /gex'

아니면 간단히 말해서

perl -pe 's/"(.+?[^\\])"/($ret = $1) =~ (s#,##g); $ret/ge'

처리할 텍스트를 명령으로 파이프하거나 마지막 명령줄 인수로 처리할 텍스트 파일을 지정할 수 있습니다.

답변4

두 번째 참조가 잘못되었습니다.

sed -e 's/\(".*\),\(.*"\)/\1 \2/g'

또한 정규식을 사용하면 텍스트의 가능한 가장 긴 부분과 일치하는 경향이 있습니다. 즉, 문자열에 따옴표로 묶인 필드가 여러 개 있는 경우에는 이 방법이 작동하지 않습니다.

sed에서 여러 참조 필드를 처리하는 방법

sed -e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' -e 's/\"//g'

이는 이 문제를 해결하는 방법이기도 합니다. 그러나 참조된 각 필드에 여러 개의 쉼표가 포함될 수 있는 입력의 경우 sed의 첫 번째 표현식은 단일 필드의 최대 쉼표 내용만큼 또는 변경되지 않을 때까지 반복되어야 합니다. 출력이 전혀.

여러 표현식으로 sed를 실행하는 것은 여러 sed 프로세스를 실행하고 모든 "tr"을 개방형 파이프로 실행하는 것보다 더 효율적입니다.

그러나 입력 형식이 올바르지 않으면 바람직하지 않은 결과가 발생할 수 있습니다. 즉, 중첩된 따옴표, 끝나지 않은 따옴표입니다.

실행 예제 사용:

echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME' \
| sed -e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' \
-e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' -e 's/\"//g'

산출:

123,ABC  DEV 23,345,534,some more  comma-separated  words,202,NAME

관련 정보