这个网站的新手,如果我提出这个问题很抱歉:
我有一个以下格式的文本文件:
file: abc
value: 123
value: 234
value: 567
file: def
value: 999
file: ghi
value: 123
value: 999
我的目标是编写一个 bash 脚本,将此文本转换为 CSV 格式,file
其中每行重复该值。上面的数据需要看起来像这样:
abc,123
abc,234
abc,567
def,999
ghi,123
ghi,999
我一直在尝试,sed
但不知道如何记住多行的文件名。我猜这可能会更容易,awk
但我还没有“抓住”awk。
将不胜感激您的帮助!
答案1
只要找到这样的键,以下awk
命令就将awk
变量设置file
为键的值file
(键是该行的第一个字段,值是第二个字段)。如果当前行没有file
键,则变量的当前值file
与当前行的值一起输出。
$ awk -F ': ' 'BEGIN { OFS="," } $1 == "file" { file = $2; next } { print file, $2 }' file
abc,123
abc,234
abc,567
def,999
ghi,123
ghi,999
请注意,这不会尝试正确引用 CSV 的值,并且它假定没有值包含字段分隔符:
(冒号+空格)。
和sed
:
sed -n \
-e '/^file: / { s///; h; }' \
-e '/^value: / { s///; G; s/\(.*\)\n\(.*\)/\2,\1/p; }' file
当file:
找到一行时,file:
前缀字符串被剥离,剩余部分存储在保留空间中。
当value:
找到一行时,value:
前缀字符串将被去除,保留空间中的文本将被附加到缓冲区的末尾,并以文字换行符作为分隔符。缓冲区中以换行符分隔的部分被交换(换行符用逗号替换)并输出。
结果和预期的一样。
这没有初始字符串后面的值key:
不能包含冒号+空格的限制。同样,最终输出不会有任何特殊的 CSV 文本编码,因此包含嵌入逗号和双引号的字段会使 CSV 解析器感到困惑。
以下内容通过在原始文件中的每行之间添加空行来修改输入。这使得该文件成为有效的“XTAB”文件,并:
作为键值分隔符。然后由 Miller ( ) 读取mlr
,它了解 CSV 的特殊引用规则并且可以读取 XTAB 格式。
Miller 从输出中读取记录awk
,并对数据执行“填充”操作file
,将前一个file
值分配给每条没有记录的记录。
随后的“过滤”操作会删除所有没有字段的记录value
。
然后输出的数据不带 CSV 标头。
awk '{ print; print "" }' file |
mlr --ixtab --ips ': ' \
--ocsv --headerless-csv-output \
fill-down -f file then filter -x 'is_absent($value)'
我修改了测试数据,以表明即使输入包含逗号和引号,也能够正确生成完全兼容的 CSV 输出:
$ cat file
file: test: here's a test
value: this is, the value
value: another so called "value"
file: abc
value: 123
value: 234
value: 567
file: def
value: 999
file: ghi
value: 123
value: 999
$ awk '{ print; print "" }' file | mlr --ixtab --ips ': ' --ocsv --headerless-csv-output fill-down -f file then filter -x 'is_absent($value)'
"this is, the value",test: here's a test
"another so called ""value""",test: here's a test
123,abc
234,abc
567,abc
999,def
123,ghi
999,ghi