我在文本文件中有以下格式的记录:
Record1
Record1
Record1
Record1
Record2
Record2
Record2
Record2
...
我需要将此文件转换为 CSV,方法是将前 3 个换行符替换为逗号并删除第 4 个换行符,得到如下输出:
Record1,Record1,Record1,Record1
Record2,Record2,Record2,Record2
...
在 Bash 中执行此操作的最佳方法是什么,其中最佳更多地是关于稳健性而不是性能——这项任务不会经常完成,但确实需要允许值包含除空格和换行符之外的几乎任何字符。
答案1
我会用 awk 来做这个
awk 'BEGIN {FS = "\n"; RS = ""; OFS = ","} {$1 = $1; print}' file
将 RS 设置为空字符串意味着 2 个或更多换行符分隔记录。
字段分隔符是一个换行符。
$1 = $1
是一种强制 awk 使用输出字段分隔符重写当前记录的惯用方法。
答案2
只是为了好玩,用python单行[1]来创建预期的结果:
$ python -c "\ 导入系统;eol='END\n';\ lines=[line.strip()+',' 如果 len(line)>1 否则 eol 用于 sys.stdin 中的行];\ 打印(''。join(lines)+eol)” \ <记录
行:
- 使用字符串启动 python
- 访问 sys.stdin,设置行结束常量
- 使用列表推导从 stdin 读取行,同时检查空行,并用 eol 标记替换这些空行
- 使用创建的行列表,连接行,打印它们
- 从哪里读取行(命令行重定向)
当您将上面的文本(不带前导 $)粘贴到(bash)终端时,您将得到这个...
记录1,记录1,记录1,记录1,结束 记录2,记录2,记录2,记录2,结束 记录1,记录1,记录1,记录1,结束 记录2,记录2,记录2,记录2,结束 记录1,记录1,记录1,记录1,结束 记录2,记录2,记录2,记录2,结束
... 从包含示例文本(重复)的“记录”读取时......
删除所有“,END”是一个简单的步骤;例如,将其全部放入 sed 中;
附加| sed -re "s/,END$//"
到最后一行。
[1] 以上内容最好输入在一行中,只需跳过\
“'”,这些是为了提高可读性而添加的。
答案3
使用磨坊主并运行
mlr --n2t --headerless-tsv-output --from input.txt \
put '$id=$1' then skip-trivial-records then \
nest --ivar "," -f 1 then \
cut -x -f id
你得到
Record1,Record1,Record1,Record1
Record2,Record2,Record2,Record2
一些说明:
skip-trivial-records
删除空行;nest --ivar "," -f 1
合并记录值,通过,