,
텍스트 파일에서 (쉼표)와 (따옴표)를 제거하고 싶습니다 "
(큰따옴표에 쉼표로 구분된 숫자가 포함된 경우에만).
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///
/d
r
y
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))
,\1
will befoobar
및\2
will bebar
. "[0-9,]*",?
: 0개 이상의0-9
or와 일치하고,
그 뒤에 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