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