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
。现在有多个rettag
s 需要在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 … < "$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 搜索和替换插入回车的主要内容,如果未能解决你的问题,请参考以下文章