대괄호 사이의 값을 같은 줄의 다른 부분에 복사하는 방법

대괄호 사이의 값을 같은 줄의 다른 부분에 복사하는 방법

다음과 같은 행이 많은 CSV 파일이 있습니다.

1003,CC,L1008,,(LB1) Urbà de Barberà del Vallès,3,,,
1006,CK,L0520,,Móra d'Ebre - Móra la Nova (estació),3,,,
1007,AV,L0358,,Granollers-Terrassa-Manresa,3,,,
1011,DD,L0480,,(781) St. Vicenç Castellet-Castellgalí-Manresa,3,,,
1012,DD,L0481,,(784) Manresa-Castellgalí-St.Vicenç-Monistrol,3,,,
1013,DD,L0487,,(783) Manresa-Pt.Vilomara-St.Vicenç-Monistrol,3,,,
...

내가 해야 할 일은 다섯 번째 열이 (세 번째 열 대신 대괄호 사이의 값을 복사하여 시작하는 경우입니다. 그렇지 않은 경우 해당 줄을 그대로 두십시오.

결과는 다음과 같습니다.

1003,CC,LB1,,(LB1) Urbà de Barberà del Vallès,3,,,
1006,CK,L0520,,Móra d'Ebre - Móra la Nova (estació),3,,,
1007,AV,L0358,,Granollers-Terrassa-Manresa,3,,,
1011,DD,781,,(781) St. Vicenç Castellet-Castellgalí-Manresa,3,,,
1012,DD,784,,(784) Manresa-Castellgalí-St.Vicenç-Monistrol,3,,,
1013,DD,783,,(783) Manresa-Pt.Vilomara-St.Vicenç-Monistrol,3,,,
...

이렇게 하려고 하는데 sed괄호 사이의 부분을 캡처할 수 있다는 것은 알지만 알 수 없는 텍스트를 바꾸는 방법을 모르겠습니다.

이것을 위해 사용될 수 있습니까 sed?

답변1

CSV에 포함된 구분 기호(따옴표로 묶인 쉼표가 포함된 쉼표로 구분된 필드)가 없다고 가정하면 Awk를 사용하면 간단합니다.

$ awk 'BEGIN{OFS=FS=","} match($5,/^\([0-9]+\)/) {$3 = substr($5,RSTART+1,RLENGTH-2)} 1' file.csv
1003,CC,L1008,,(LB1) Urbà de Barberà del Vallès,3,,,
1006,CK,L0520,,Móra d'Ebre - Móra la Nova (estació),3,,,
1007,AV,L0358,,Granollers-Terrassa-Manresa,3,,,
1011,DD,781,,(781) St. Vicenç Castellet-Castellgalí-Manresa,3,,,
1012,DD,784,,(784) Manresa-Castellgalí-St.Vicenç-Monistrol,3,,,
1013,DD,783,,(783) Manresa-Pt.Vilomara-St.Vicenç-Monistrol,3,,,

Sed 사용(동일한 제한 사항 있음):

$ sed -E 's/^([^,]*),([^,]*),([^,]*),([^,]*),\(([0-9]+)\)/\1,\2,\5,\4,(\5)/' file.csv
1003,CC,L1008,,(LB1) Urbà de Barberà del Vallès,3,,,
1006,CK,L0520,,Móra d'Ebre - Móra la Nova (estació),3,,,
1007,AV,L0358,,Granollers-Terrassa-Manresa,3,,,
1011,DD,781,,(781) St. Vicenç Castellet-Castellgalí-Manresa,3,,,
1012,DD,784,,(784) Manresa-Castellgalí-St.Vicenç-Monistrol,3,,,
1013,DD,783,,(783) Manresa-Pt.Vilomara-St.Vicenç-Monistrol,3,,,

보다 강력하게는 Perl의 Text::CSV 모듈을 사용하십시오.

$ perl -C -MText::CSV -lne '
    BEGIN{$p = Text::CSV->new()} 
    @f = $p->fields() if $p->parse($_); 
    $f[2] = $1 if $f[4] =~ /^\((\d+)\)/; 
    print join ",", @f
  ' file.csv
1003,CC,L1008,,(LB1) Urbà de Barberà del Vallès,3,,,
1006,CK,L0520,,Móra d'Ebre - Móra la Nova (estació),3,,,
1007,AV,L0358,,Granollers-Terrassa-Manresa,3,,,
1011,DD,781,,(781) St. Vicenç Castellet-Castellgalí-Manresa,3,,,
1012,DD,784,,(784) Manresa-Castellgalí-St.Vicenç-Monistrol,3,,,
1013,DD,783,,(783) Manresa-Pt.Vilomara-St.Vicenç-Monistrol,3,,,

답변2

왜 파이썬을 사용하지 않습니까? (파일 이름을 파일 이름으로 바꾸십시오)

import re, csv
for line in list(csv.reader(open('filename', 'r'))):
    matches = re.findall('\([0-9]*\)',line[4])
    if matches:
        line[2] = matches[0]
    print(','.join(line))

답변3

다음 스크립트로 완료

count=`awk '{print NR}' filename| sort -nr| sed -n '1p'`

for ((i=1;i<=$count;i++)); do h=`awk -v i="$count" -F ","  'NR==i && $5 ~ /^\(/{print $5}' filename | awk '{print $1}'| sed -e  "s/(//g" -e "s/)//g"| wc -l`; if [[ $h != 0 ]]; then k=`awk -v i="$count" -F ","  'NR==i && $5 ~ /^\(/{print $5}' filename | awk '{print $1}'| sed -e  "s/(//g" -e "s/)//g"`; awk -v i="$count" -v k="$k" -F "," 'NR==i && $5 ~ /^\(/{$3=k;print $0}' filename| sed "s/ /,/g"; else awk -v i="$count" 'NR==i {print $0}' filename; fi; done

산출

1003,CC,LB1,,(LB1),Urbà,de,Barberà,del,Vallès,3,,,
1006,CK,L0520,,Móra d'Ebre - Móra la Nova (estació),3,,,
1007,AV,L0358,,Granollers-Terrassa-Manresa,3,,,
1011,DD,781,,(781),St.,Vicenç,Castellet-Castellgalí-Manresa,3,,,
1012,DD,784,,(784),Manresa-Castellgalí-St.Vicenç-Monistrol,3,,,
1013,DD,783,,(783),Manresa-Pt.Vilomara-St.Vicenç-Monistrol,3,,,

답변4

awksed버전강철 드라이버제안된 직업은 정말 매력적이었고 현재 환경에서 구현하기가 매우 쉬웠습니다.

대괄호 사이의 코드에 문자, 공백 및 점을 허용하도록 약간 개선했습니다.

awk 'BEGIN{OFS=FS=","} match($5,/^\([a-zA-Z0-9 .]+\)/) {$3 = substr($5,RSTART+1,RLENGTH-2)} 1' file.csv

sed -E 's/^([^,]*),([^,]*),([^,]*),([^,]*),\(([a-zA-Z0-9 .]+)\)/\1,\2,\5,\4,(\5)/' file.csv

다른 버전은 작동하지만 제가 하고 있는 작업 흐름에는 맞지 않습니다.

감사해요!

관련 정보