처음 몇 행이 다음과 같은 CSV가 있습니다.
c("4288", "57534"),MIB1
c("2272", "2385"),FHIT
c("5550", "10531", "56239"),PREP
c("25809", "23669"),TTLL1
괄호 안에 그룹화된 모든 항목이 하나의 변수가 되도록 변수 수를 조작하고 싶습니다. 불행하게도 내 문서에는 괄호 안에 여러 개의 쉼표로 구분된 값이 있는 3행과 같은 여러 항목이 있습니다.
괄호 안의 쉼표에만 작동하는 sed 표현식이 있나요?
예상되는 출력은 다음과 같습니다.
c("4288" "57534"), MIB1
c("2272" "2385"),FHIT
c("5550" "10531" "56239"),PREP
c("25809" "23669"),TTLL1
건배.
답변1
고급 정규 표현식 perl
에는 사용 하지 마세요.sed
perl -pe 's/(?:\G[^,)]*|\([^,)]*)\K,(?=.*?\))//g' input.csv
c("4288" "57534"),MIB1
c("2272" "2385"),FHIT
c("5550" "10531" "56239"),PREP
c("25809" "23669"),TTLL1
이렇게 하면 괄호 안에 나타나는 쉼표가 모두 제거됩니다.
답변2
나는 이미 같은 해결책으로 대답했습니다여기, 이는 귀하의 질문에도 적용되며 여기에서 약간 수정되었습니다.
sed -E ':loop s/(\([^)]*),([^)]*\))/\1\2/; t loop' infile
분해:
노트: 이스케이프되지 않은 문자 클래스 (
또는 )
외부 문자 클래스는 이스케이프된 문자 [...]
클래스와 일치하는 데 사용됩니다. \(
합계는 음수 일치입니다.\)
[...]
(
)
^
[^)]
임의의 단일 문자이지만)
".
그런 다음 우리는 다음을 가집니다:
(\([^)]*)
: 첫 번째 그룹의 게임은 \1
뒤쪽에 있는 심판을 의미합니다.
,
: 단일 쉼표와 일치합니다.
([^)]*\))
: 두 번째 게임 세트를 소급하여 \2
말합니다.
다음과 같은 예제 라인을 고려하고 일치가 어떻게 작동하는지 설명하십시오.
c(("4288", "57534", "somtoher")),d("f1", "f2", "f3"),MIB1
이는 (\([^)]*),([^)]*\))
다음과 일치합니다.
첫 번째 여는 괄호부터 시작하여
(
a를 제외한 모든 항목부터 마지막 닫는 괄호까지)
; 따라서 첫 번째 일치 집합은 위 예제 줄의 일부와 일치합니다 .,
)
\1
(("4288", "57534",
그런 다음 마지막부터
,
첫 번째 닫는 괄호까지의 모든 내용과)
그 자체가 두 번째 일치 항목 집합에 포함되며 위 예제 줄의 일부\2
가 됩니다 ."somtoher")
replacement 섹션에서는
\1\2
일치하는 두 그룹을 다시 가져오지만 이들 사이의 쉼표를 제거합니다.:loop s///; t loop
; sed 루프에서(
& 사이의 모든 쉼표(레이블로 사용됨)가 지워질 때까지 1~3단계를 수행합니다.)
loop
첫 번째 시도에서 예제 줄은 다음과 같이 변경됩니다.
c(("4288", "57534" "somtoher")),d("f1", "f2", "f3"),MIB1
두 번째 시도는 다음과 같습니다.
c(("4288" "57534" "somtoher")),d("f1", "f2", "f3"),MIB1
세 번째 시도는 다음과 같습니다.
c(("4288" "57534" "somtoher")),d("f1", "f2" "f3"),MIB1
등.