sed -i与进程替换

时间:2016-01-24 18:56:04

标签: bash sed grep

我想搜索成绩并将其替换为以下内容:

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命令,因此它无法访问原始文件。有没有其他方法可以做到这一点?

3 个答案:

答案 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