awk에서 csv 열을 기록하고 빈 필드를 고려하십시오.

awk에서 csv 열을 기록하고 빈 필드를 고려하십시오.

여러 열이 포함된 csv 파일이 있다고 가정해 보겠습니다. NF일정하지 않습니다. 현재 4보다 큰 열을 소문자로 바꾸려면 다음을 수행합니다.

#!/usr/bin/awk
#call with `awk -f lowercase.awk in.csv > out.csv`
BEGIN {
    OFS=",";
    FPAT="([^,]+)|(\"[^\"]+\")";
}
{
    for (i=1; i<=NF; i++){
        if(i>4 && $i){
            $i = tolower($i);
        }
    }
    print $0;
}

그러나 이는 csv 파일에서 인접한 필드 구분 기호(반복되는 쉼표로 표시되는 빈 열)를 고려하지 않습니다 ,,,,. 이를 어떻게 고려합니까? 나는 좋아하지 않는다해결책은 여기에 있습니다일반화가 잘 이루어지지 않기 때문입니다(조건 확인이 많기 때문에 실제 애플리케이션은 NF40보다 크고 70보다 작습니다).

단위 테스트:

입력.csv

apple,orange,banana,cherry,MELON,"Fruit salad",grape
"Lots of vegtables",CUCUMBER,carrot,potato,RADISH,BeetrOOT
Bread,BAGEL,,,,Croissant

출력.csv

apple,orange,banana,cherry,melon,"fruit salad",grape
"Lots of vegtables",CUCUMBER,carrot,potato,radish,beetroot
Bread,BAGEL,,,,croissant

답변1

완료하기 쉽습니다sed

sed 's/\(\([^,]*,\)\{4\}\)\(.*\)/\1\L\3/' file.csv

이스케이프 문자가 마음에 들지 않으면 스크립트를 수정할 수 있습니다(GNU sed의 경우).

sed -r 's/(([^,]*,){4})(.*)/\1\L\3/' file.csv

쉼표가 뒤에 오는 쉼표가 아닌 기호(0 포함)의 4개 그룹을 찾아 변경하지 않은 채로 두고( ) \1문자열의 나머지 부분( ) \3에 있는 모든 항목을 더 낮은 버전으로 바꿉니다 .
또는 에 의해 cut그리고paste

paste -d, <(cut -d, -f-4 file.csv) <(cut -d, -f5- file.csv | tr '[[:upper:]]' '[[:lower:]]')

답변2

제가 질문을 잘못 이해했을 수도 있으니 양해 부탁드립니다. tolower하지만 4(또는 40 또는 원하는 항목)보다 큰 모든 필드를 간단하게 처리할 수 있어야 하는 것 같습니다 . 예를 들어:

BEGIN {
    OFS = ","
   }
{
    for (i = 4 ; i <= NF ; i++) {
        $i = tolower($i)
        }
    $1 = $1
    print
}

결국 tolower(*some empty field*)그것은 완전히 비어있었습니다. 이것이 작동하지 않을 이유가 있습니까?

편집: 내 결과:

apple,orange,banana,cherry,melon,"fruit salad",grape
"Lots of vegtables",CUCUMBER,carrot,potato,radish,beetroot
Bread,BAGEL,,,,croissant

관련 정보