특정 열의 구분 기호 업데이트

특정 열의 구분 기호 업데이트

7개의 필드가 있는 쉼표로 구분된 파일이 있습니다. 그러나 이러한 필드 중 하나가 ,값에 포함됩니다. |로 파일을 변경하지 않고 파일 구분 기호를 로 변경하고 싶습니다 ,.

내가 가지고 있는 파일:

Name,Age,Country,ID,Address,Category,DOB
John Doe,19,England,3653,Manchester, England,Main Worker,20-05-1995

원하는 출력:

Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Part Time Worker|20-05-1995

여러 가지 솔루션을 시도했지만 원하는 것을 달성하지 못했습니다. 처음 4개 열의 구분 기호만 업데이트하는 다음 명령을 시도했습니다.

sed 's/,/|/;s/,/|/;s/,/|/;s/,/|/' file

내가 찾고 있는 방법은 처음 4개 열과 마지막 2개 열의 구분 기호를 업데이트하는 것입니다. 이렇게 하면 주소 열을 변경하지 않고도 구분된 파일을 업데이트할 수 있습니다.

아래 코드를 생각해 냈는데 이렇게 하면 ,와 사이의 내용이 제거됩니다.ManchesterEngland

awk '{ORS="";N=split($0,a,",");\
            print a[1]"|"a[2]"|"a[3]"|"a[4]"|"; \
            for(i=5;i<N-1;i++) print a[i]; 
            print "|"a[N-1]"|"a[N] }'

답변1

당신은 awk시도 할 수 있습니다:

awk -F, -v OFS='|' 'NR==1{print $0} NR>1{$5 = $5 FS $6; print $1,$2,$3,$4,$5,$7,$8}' file
Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995

답변2

bash를 사용하면 주소 필드에 있는 쉼표 수에 관계없이 이를 처리할 수 있습니다.

# function to join strings with a separator
join() { 
    local IFS=$1
    shift
    printf '%s\n' "$*"
}

# process the file
{ 
    IFS=, read -ra header
    join '|' "${header[@]}"
    f=${#header[@]}                     # expected num of fields

    while IFS=, read -ra row; do
        n=${#row[@]}                    # actual num

        # with a placeholder for the address
        real_row=("${row[@]:0:4}" __ "${row[@]:n-2}")

        # set the actual address
        real_row[4]=$(join ',' "${row[@]:4:n-f+1}")

        join '|' "${real_row[@]}"
    done
} < file

산출

Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995

답변3

어떤 쉼표를 유지하고 어떤 것을 변경해야 하는지 어떻게 아는지 설명하지 않으셨습니다. 귀하가 제공한 단일 예제 라인을 기반으로 ,공백 뒤의 모든 내용을 다음으로 바꾸 십시오 |.

$ sed -E 's/,(\S)/\|\1/g' file
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995

또는 제목을 변경하고 싶지 않은 경우:

$ sed -E '2,${s/,(\S)/\|\1/g}' file
Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995

또는 공백에 의존할 수 없고 대신 5번째 쉼표를 제외한 줄의 모든 쉼표를 다음과 같이 바꿔야 하는 경우에는 어떻게 될까요? "이 줄에 필드가 7개보다 많으면 ,이 줄의 5번째 필드를 일부로 처리됨으로 바꿉니다. 4번째 필드이며 구분 기호로 사용되지 않습니다." 그렇다면 다음이 도움이 될 것입니다.

$ $ perl -F, -lane 'if($#F>6){$F[4].=",$F[5]"; splice(@F,5,1)} print join("|",@F)' file
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995

또는 헤더를 변경하지 않으려면 다음을 사용하십시오.


$ perl -F, -lane 'if($#F>6){$F[4].=",$F[5]"; splice(@F,5,1)} $.==1 ? print : print join("|",@F)' file
Name,Age,Country,ID,Address,Category,DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995

답변4

$ perl -F, -lne 'if ($#F == 7) {$F[4] .= ",$F[5]"; splice @F,5,1};
                 print join("|",@F);' input.csv
Name|Age|Country|ID|Address|Category|DOB
John Doe|19|England|3653|Manchester, England|Main Worker|20-05-1995

이 perl one-liner는 각 입력 줄에 쉼표로 구분된 필드가 몇 개 있는지 확인합니다. 필드가 8개 있는 경우 필드 4에 쉼표와 필드 5의 내용을 추가한 다음 를 사용하여 필드 5를 삭제합니다 splice().

@FPerl을 사용하거나 호출할 때 awk의 $1, $2, $3 등에 해당하는 자동 분할 배열을 사용하여 이 모든 작업을 수행합니다 .-F-a

|그런 다음 필드 4와 5를 변경했는지 여부에 관계없이 파이프 문자로 연결된 @F 배열을 인쇄합니다 .

참고: Perl 배열은 1이 아닌 0부터 시작합니다. $#F@F 배열의 마지막 인덱스 번호를 반환하므로 == 7테스트가 가 아닙니다 == 8. 8개 필드가 있는 레코드에서 @F의 인덱스는 0..7입니다. 이는 또한 5번째 필드(주소)가 $F[4]가 아닌 로 호출된다는 의미이기도 합니다 $F[5].

관련 정보