,
텍스트 파일에서 (쉼표)와 (따옴표)도 제거하고 싶습니다 "
(큰따옴표에 쉼표로 구분된 숫자가 포함된 경우에만).
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///
, 로 쓸 수도 있음 )을 변환합니다. 번역 횟수 대신 번역된 문자열 값을 얻으려면 플래그가 필요 합니다 .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 be 입니다bar
. "[0-9,]*",?
: 0개 이상의0-9
or 와 일치하고,
그 뒤에 0 또는 1 이 옵니다,
.("[0-9,]*",?)*
: 위 항목 중 0개 이상과 일치합니다."[0-9,]*
: a 바로 다음에 오는 0개 이상의0-9
or 와 일치합니다.,
"
- 우선, 이 구문을 사용하면 :
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
위 코드에서는 숫자를 인식하고 삽입된 쉼표를 제거했습니다. 정규식은 다음과 같은 사실을 이용합니다.중첩 구조Raku의 새로운 ~ 물결표(중첩) 표기법으로 표시할 수 있습니다. 즉, \" ~ \" [\d+]
"" 큰따옴표로 둘러싸인 하나 이상의 숫자"를 의미합니다.
추가적으로,반복되는 구조%
반복 구조에 대한 Raku의 새로운 수정 수량자로 표시할 수 있습니다 . [\d+] ** 2..* % "," 표기는 " ,
이 패턴이 ** 2..*
두 번 이상 반복되고 쉼표로 구분된 하나 이상의 숫자를 의미합니다. [후행 구분 기호가 있는 경우(예: 쉼표), 구문] %%
대신 에 a를 사용하세요.%
이것은 단지 시작일 뿐입니다. 대체 구분 기호, 삽입된 줄 바꿈, 삽입된 쉼표, 잠재적으로 공백인 필드 등이 있는 CSV 파일은 실제로 Raku Text::CSV
모듈과 같은 진정한 CSV 파서로 처리되어야 합니다. 자세한 내용은 아래 링크를 참조하세요.
https://docs.raku.org/언어/regexes
https://raku.land/github:Tux/Text::CSV
https://raku.org