【发布时间】:2016-09-25 12:13:39
【问题描述】:
我正在遍历一个 CSV 文件。文件的每一行的格式如下(它是 Open Street Maps 数据):
planet_85.287_27.665_51a5fb91,AcDbEntity:AcDbPolyline,{ [名称] Purano Bus Park-Thimi [type] route [route] microbus [ref] 10 } { [Id] 13.0 [Srid] 3857 [FieldsTableId]
以下格式:
图层、子类、扩展实体、线型、实体句柄、文本
我想为Name 添加一个新列。我可以通过截断 [name] 之前和 [.此代码成功创建了一个包含所有名称的换行符文件(我将其作为 CSV 打开,然后将其复制粘贴到原始文件中作为新列)。
cat /path/to/myfile.csv | while read line
do
if [[ ${line} == *"name"* ]]
then
printf "$(echo $line | LC_ALL=C sed 's/^.*name\]//g'| LC_ALL=C cut -f1 -d'[') \n"
else
printf "\n"
fi
done >/path/to/newrow.csv
这个系统显然不是最理想的——我更愿意打印整个最后一行。但是当我用这个替换 printf 行时:
printf "$line,$(echo $line | LC_ALL=C sed 's/^.*name\]//g'| LC_ALL=C cut -f1 -d'[') \n"
它打印行但不打印名称。我尝试在单独的打印语句中打印它们,打印行然后回显名称,将名称保存在变量中然后打印,以及许多其他技术,每次我要么a)只打印行,要么b) 在新行上打印名称,这会破坏 CSV 格式。
我做错了什么?如何打印完整的原始行,并将名称附加为末尾的新列?
注意:我在 MacBook Pro 15" Retina 上的 macOS Sierra 上的终端中运行它。
【问题讨论】:
-
仅供参考 -- 使用
printf,替换只能在后续参数中,而不是格式字符串本身。 -
...并且每行运行一次
sed和cut非常、非常效率低下——如果你要在一行上进行处理——逐行,尝试改用bash-native string manipulation。 -
@CharlesDuffy 感谢您的意见。明天我会阅读更多的手册页。我参加了关于 Bash 和 C 的非常严格的课程,但那可能是 5 个月前的事了,从那以后我没有做过任何课程,所以目前我完全没有练习!
-
顺便说一句,
LC_ALL=C通常是矫枉过正。根据您要抑制的警告的具体内容,您可能可以使用LC_CTYPE=C或LC_COLLATE=C(如果您愿意,只在脚本顶部导出一次);这样错误消息和日期/时间格式仍然适合用户的首选语言。
标签: bash macos shell csv printf