transpose/unfold 行内嵌套数据的命令行
Command line to transpose/unfold nested data within rows
用分隔数据展开一行的聪明而简洁的方法是什么?我可以想象一个在 ruby 或 perl 中逐行处理的小脚本,但这可以优雅地完成吗?
来自这里:
alpha @ ä | b | ç @ 1.1 | 2.1 | 3.1
beta @ d | é | f @ 4.2 | 5.2 | 6.2
进入这个:
alpha @ ä @ 1.1
alpha @ b @ 2.1
alpha @ ç @ 3.1
beta @ d @ 4.2
beta @ é @ 5.2
beta @ f @ 6.2
总是有 3 个主要列,第 1 列总是内容,第 2 列和第 3 列有不可预测的非空内容。例如,我可以在一行中有 50 个项目。第 1 列和第 2 列可能有 [^a-zA-Z](即 unicode)。只要简洁,perl 或 ruby 中的一行就可以了。 sed 总是受欢迎的,但我认为这超出了 sed 的能力范围。
我正在使用 MacOS。
我的实际数据的格式和分隔符略有不同;例如,我使用制表符而不是 @,并且没有空格,但是 @ 在这里更容易阅读。让我的数据符合这个或类似的语法对我来说是微不足道的。
$ awk -F@ '{n=split(,a,"|"); split(,b,"|"); for (i=1;i<=n;i++)print "@" a[i] "@" b[i];}' file
alpha @ ä @ 1.1
alpha @ b @ 2.1
alpha @ ç @ 3.1
beta @ d @ 4.2
beta @ é @ 5.2
beta @ f @ 6.2
以上是使用 GNU awk 测试的。
工作原理
-F@
将字段分隔符设置为 @
。如果您更喜欢制表符,只需将 @
替换为 "\t"
。
{n=split(,a,"|"); split(,b,"|")
用分隔符|
拆分第二列和第三列,并将结果分别存储到数组a
和b
中。数组 a
的长度保存在变量 n
.
for (i=1;i<=n;i++)print "@" a[i] "@" b[i]
打印输出。
$ awk -F'[@|]' -v OFS='@' '{n=(NF-1)/2; for (i=2;i<=(n+1);i++) print , $i, $(i+n)}' file
alpha @ ä @ 1.1
alpha @ b @ 2.1
alpha @ ç @ 3.1
beta @ d @ 4.2
beta @ é @ 5.2
beta @ f @ 6.2
用分隔数据展开一行的聪明而简洁的方法是什么?我可以想象一个在 ruby 或 perl 中逐行处理的小脚本,但这可以优雅地完成吗?
来自这里:
alpha @ ä | b | ç @ 1.1 | 2.1 | 3.1
beta @ d | é | f @ 4.2 | 5.2 | 6.2
进入这个:
alpha @ ä @ 1.1
alpha @ b @ 2.1
alpha @ ç @ 3.1
beta @ d @ 4.2
beta @ é @ 5.2
beta @ f @ 6.2
总是有 3 个主要列,第 1 列总是内容,第 2 列和第 3 列有不可预测的非空内容。例如,我可以在一行中有 50 个项目。第 1 列和第 2 列可能有 [^a-zA-Z](即 unicode)。只要简洁,perl 或 ruby 中的一行就可以了。 sed 总是受欢迎的,但我认为这超出了 sed 的能力范围。
我正在使用 MacOS。
我的实际数据的格式和分隔符略有不同;例如,我使用制表符而不是 @,并且没有空格,但是 @ 在这里更容易阅读。让我的数据符合这个或类似的语法对我来说是微不足道的。
$ awk -F@ '{n=split(,a,"|"); split(,b,"|"); for (i=1;i<=n;i++)print "@" a[i] "@" b[i];}' file
alpha @ ä @ 1.1
alpha @ b @ 2.1
alpha @ ç @ 3.1
beta @ d @ 4.2
beta @ é @ 5.2
beta @ f @ 6.2
以上是使用 GNU awk 测试的。
工作原理
-F@
将字段分隔符设置为
@
。如果您更喜欢制表符,只需将@
替换为"\t"
。{n=split(,a,"|"); split(,b,"|")
用分隔符
|
拆分第二列和第三列,并将结果分别存储到数组a
和b
中。数组a
的长度保存在变量n
.for (i=1;i<=n;i++)print "@" a[i] "@" b[i]
打印输出。
$ awk -F'[@|]' -v OFS='@' '{n=(NF-1)/2; for (i=2;i<=(n+1);i++) print , $i, $(i+n)}' file
alpha @ ä @ 1.1
alpha @ b @ 2.1
alpha @ ç @ 3.1
beta @ d @ 4.2
beta @ é @ 5.2
beta @ f @ 6.2