Sed搜索和替换CSV文件插入回车符

时间:2017-04-12 19:09:36

标签: bash shell sed

我有一个文件retimp_info.csv,其中包含两列和约500行,如下所示:

rettag, retid  
231,1    

以及包含多行和多列的文件mdb_ret_exp.csv

a,s,d,231,f,g
a,s,d,345,f,g

因此,目标是从第一个文件中查找并替换rettagretid的匹配项。现在需要在rettag内替换多个mdb_ret_exp.csv。 (使用逗号,以便可以指定该列,以便该数字出现在我可能不知道的任何地方,即 - 不同的列)。

这是我试过的:

while IFS="," read -r rettag retid; do
  sed -i "s/,$rettag,/,$retid,/" mdb_ret_exp.csv
done < $HOME/retimp_info.csv

它几乎可以工作,但每次更换都会增加额外的回车次数:

a,s,d,1
,f,g
a,s,d,345,f,g

我预计它仍会保持在一条线上:

a,s,d,1,f,g
a,s,d,345,f,g

如何避免额外的回车?

3 个答案:

答案 0 :(得分:1)

这很可能是由retimp_info.csv具有DOS / Windows样式\r\n行结尾引起的。您可以在阅读时将其从文件中删除:

cat "$HOME/retimp_info.csv" | tr -d '\r' | while IFS="," read -r rettag retid; do
  sed -i "s/,$rettag,/,$retid,/" mdb_ret_exp.csv
done

或者事先用dos2unix从文件中删除它们,或者在文本编辑器中打开文件,选择“Unix line endings”或等效选项,然后再次保存。

答案 1 :(得分:1)

你正在咆哮错误的树。就这样做:

awk '
BEGIN { FS=OFS="," }
NR==FNR { map[$1] = $2; next }
{
    for (i=1; i<=NF; i++) {
        if ($i in map) {
            $i = map[$i]
        }
    }
    print
}
' $HOME/retimp_info.csv mdb_ret_exp.csv

这将解决您当前遇到的所有问题以及您可能尚未遇到的问题,但可能会解决这些问题:

  1. 执行regexp而不是字符串比较,
  2. 您当前的方法不适用于第一个或最后一个 每行的字段和
  3. 如你所说,你的sed循环可以在替换之后替换它们
  4. 除了更加强大之外,awk方法还将比您当前的方法快至少一个数量级。另请参阅why-is-using-a-shell-loop-to-process-text-considered-bad-practice

    哦,首先在输入文件上运行dos2unix或类似内容,因为它们当前具有Windows控件-M行结尾(使用cat -v file查看它们)。

答案 2 :(得分:-1)

更新:使用以下内容 -
while IFS="," read -r rettag retid; do sed -i "s/,$rettag,/,$retid,/g" mdb_ret_exp.csv done < $home/retimp_info.csv
工作正常,但现在它取代了正确的值(位于行/行的中间)后,它插入一个回车 - 导致以下信息被移动到下一行

即:
a,s,d,231,f,g

现在是 -
A,S,d,1个
,F,G
需要,f,g保持在同一条线上......