我想搜索成绩并将其替换为以下内容:
input_q1.csv:
roll,name,total,rank,grade
001,A B,78,23,C
003,F YZ,100,1,*
004,G H,12,112,F
输出为:
input_q1.csv:
roll,name,total,rank,grade
001,A B,78,23,Average
003,F YZ,100,1,Good
004,G H,12,112,Fail
这是我的代码:
#!/bin/bash
if cut -d"," -f5 input_q1.csv | grep -q "\*\|A"; then
sed -i 's/\*/Good/g;s/A/Good/g' <(cut -d"," -f5 input_q1.csv)
fi
if cut -d"," -f5 input_q1.csv | grep -q "B\|C"; then
sed -i 's/B/Average/g;s/C/Average/g' <(cut -d"," -f5 input_q1.csv)
fi
if cut -d"," -f5 input_q1.csv | grep -q "D"; then
sed -i 's/D/Poor/g;' <(cut -d"," -f5 input_q1.csv)
fi
if cut -d"," -f5 input_q1.csv | grep -q "F"; then
sed -i 's/F/Fail/g' <(cut -d"," -f5 input_q1.csv)
fi
我想用原始文件覆盖,即input_q1.csv,但我知道进程替换会创建一个临时文件,我将传递给sed命令,因此它无法访问原始文件。有没有其他方法可以做到这一点?
答案 0 :(得分:2)
创建一个文件,例如sed.dat:
s/,\*$/,Good/
s/,A$/,Good/
s/,B$/,Average/
s/,C$/,Average/
s/,D$/,Poor/
s/,F$/,Fail/
并使用:
sed -f sed.dat input_q1.csv
输出:
roll,name,total,rank,grade 001,A B,78,23,Average 003,F YZ,100,1,Good 004,G H,12,112,Fail
如果你想“编辑你的文件input_q1.csv”,请添加sed的选项-i
。
答案 1 :(得分:0)
您可以使用awk
。
假设:
$ cat /tmp/so.csv
roll,name,total,rank,grade
001,A B,78,23,C
003,F YZ,100,1,*
004,G H,12,112,F
您可以使用awk
替换:
$ awk -F "," 'BEGIN {OFS=","; gr["C"]="Average"; gr["*"]="Good"; gr["F"]="Fail"} { if (NR>1) {print $1,$2,$3,$4,gr[$5]} else {print $0}}' /tmp/so.csv
roll,name,total,rank,grade
001,A B,78,23,Average
003,F YZ,100,1,Good
004,G H,12,112,Fail
然后将其复制到临时文件,然后复制原始文件:
$ awk -F "," 'BEGIN {OFS=","; gr["C"]="Average"; gr["*"]="Good"; gr["F"]="Fail"} { if (NR>1) {print $1,$2,$3,$4,gr[$5]} else {print $0}}' /tmp/so.csv > /tmp/tmp && mv /tmp/tmp /tmp/so.csv
$ cat /tmp/so.csv
roll,name,total,rank,grade
001,A B,78,23,Average
003,F YZ,100,1,Good
004,G H,12,112,Fail
答案 2 :(得分:0)
虽然我认为@ dawg的解决方案更好,应该是接受的答案,但以下是纯粹的Bash解决方案,以防您感兴趣:
grades_to_words () {
local IFS=,
while read -ra arr; do
len=${#arr[@]}
grade=${arr[len-1]}
case "$grade" in
C) printf '%s,%s\n' "${arr[*]:0:len-1}" 'Average';;
F) printf '%s,%s\n' "${arr[*]:0:len-1}" 'Fail';;
\*) printf '%s,%s\n' "${arr[*]:0:len-1}" 'Good';;
esac
done
}
使用示例:
$ # The first 'read' ignores the titles line.
$ { read; grades_to_words; } < input_q1.csv
001,A B,78,23,Average
003,F YZ,100,1,Good
004,G H,12,112,Fail