假设我有一个包含几列的 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)非逗号符号,后跟逗号并保持不变(\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