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

Posted

技术标签:

【中文标题】CSV 文件中的 Sed 搜索和替换插入回车【英文标题】:Sed search&replace from CSV file inserts carriage return 【发布时间】:2017-09-08 17:18:01 【问题描述】:

我有一个文件 retimp_info.csv,它有两列和大约 500 行,如下所示:

rettag, retid  
231,1    

还有一个包含多行多列的文件mdb_ret_exp.csv

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

所以目标是从第一个文件中找到rettag 并将其替换为retid。现在有多个rettags 需要在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

如何避免额外的回车?

【问题讨论】:

看起来你正在运行s/,231,,/,1,/,而你想要s/, 231,/, 1,/(注意空格和逗号的区别)。您是否已采取任何措施来隔离问题? 是的,我用我的 ifs 解决了这个简短的问题 > 从某种意义上说是 IFS 错误。 【参考方案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 行尾”或等效选项,然后再次保存,将它们从文件中删除。

【讨论】:

使用tr … &lt; "$HOME/retimp_info.csv";没有必要把猫拖进去。【参考方案2】:

你找错树了。只需这样做:

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

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

    进行正则表达式而不是字符串比较,并且 事实上,您当前的方法不适用于第一个或最后一个 每行的字段,以及 如您所写,您的 sed 循环可以在完成替换后替换它们

除了更加健壮之外,awk 方法还将比您当前的方法至少快一个数量级。另见why-is-using-a-shell-loop-to-process-text-considered-bad-practice。

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

【讨论】:

【参考方案3】:

更新:使用以下 -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 保持在同一行...

【讨论】:

这确实应该作为额外信息编辑到问题中。

以上是关于CSV 文件中的 Sed 搜索和替换插入回车的主要内容,如果未能解决你的问题,请参考以下文章

shell中如何把回车换行置换成半角空格?

使用 SED / VBS 将标题行插入 CSV

替换 SQL 中的换行符

如何使用sed搜索和替换]、[? [关闭]

sed多行模板替换

sed如何在文件的最后 插入一行文字