我有一个如下所示的文件:
10-04-2022 00:39:13,36707,1455008753,32
11-05-2022 00:39:13,36708,1555008753,26
21-05-2022 00:39:13,36708,1555408753,15
12-06-2022 00:39:13,36709,1655008753
因为最后一个字段的值与下一行的运行时间相关,所以我想将它们向下移动到这种方式以便与 gnuplot 一起使用。
10-04-2022 00:39:13,36707,1455008753,
11-05-2022 00:39:13,36708,1555008753,32
21-05-2022 00:39:13,36708,1555408753,26
12-06-2022 00:39:13,36709,1655008753,15
答案1
一个简单的 awk 脚本可以做到这一点:
awk 'BEGIN {FS=OFS=","} { tmp=$NF; $NF=save; print; save=tmp; }' < input > output
这会将第四个字段保存到临时变量中,用之前保存的值替换第四个字段,然后打印新行。打印后,它会保存第四个字段的先前值以供下一次迭代使用。在第一行,“save”d值为空(默认的awk行为),这达到了预期的结果。
“BEGIN”部分将字段分隔符(用于分割输入)和输出字段分隔符(在打印行/字段时使用)设置为逗号。请参阅本地awk
手册页、各种在线参考资料或awk 的开放组基本规范了解更多。
答案2
另一个awk
解决方案,在 GNU awk
5.1.0 上测试。
$ awk -F, -v OFS=, '{print $1,$2,$3,x;x=$NF}' myfile
10-04-2022 00:39:13,36707,1455008753,
11-05-2022 00:39:13,36708,1555008753,32
21-05-2022 00:39:13,36708,1555408753,26
12-06-2022 00:39:13,36709,1655008753,15
$
答案3
使用乐(以前称为 Perl_6)
raku -e 'my @a = lines>>.split(","); my $m = @a>>.elems.max; \
.flat.join(",").put for [Z] @a>>.[0..$m-2], ("", @a>>.[$m-1]).flat;'
或者
raku -e 'my @a = lines.map: *.split(","); my $m = @a.map(*.elems).max; \
.flat.join(",").put for [Z] @a.map(*.[0..$m-2]), ("", @a.map: *.[$m-1]).flat;'
这个 Raku 答案有点长,但也更像是一个通用解决方案,因为每行的列数不是硬编码的:max
计算文件范围。
简而言之(两个例子),lines
都是读入的,每个都split
用,
逗号分隔,并存储在@a
数组中。计算许多(列)并将其存储max
为。然后,使用 Raku 的“Zip Reduction”运算符从其后面的两个列表中逐一拉出元素:这些元素在 out 中被整理并重新组合在一起,这样现在一个空字符串占据了第一个列表的末尾行,后续索引值将向下移动一行。elems
$m
[Z]
flat
join
put
""
@a[$m-1]
注意:Raku 不会自动展平数组元素,因此您必须flat
手动将它们展平为十个(如果需要)。
在这两个例子中,我试图展示 Raku 的>>
“超级”运算符如何类似于map
对单个元素执行 ping 函数/索引,或者.map(*.fn)
(在方法链的末尾)使用冒号形式.map: *.fn;
,这可以减少数量所需的括号数。
输入示例:
10-04-2022 00:39:13,36707,1455008753,32
11-05-2022 00:39:13,36708,1555008753,26
21-05-2022 00:39:13,36708,1555408753,15
12-06-2022 00:39:13,36709,1655008753
示例输出:
10-04-2022 00:39:13,36707,1455008753,
11-05-2022 00:39:13,36708,1555008753,32
21-05-2022 00:39:13,36708,1555408753,26
12-06-2022 00:39:13,36709,1655008753,15
附录:这是另一种 Raku 方法,这次将行/列展开为单独的元素,并使用rotor
.它给出与上面完全相同的结果:
raku -e 'my @a = lines>>.split(",").flat; my @b = @a[3,7,11...*]; \
@a.=rotor(3 => 1); @a.=map(*.join(",")); @b.=unshift(""); \
.join(",").put for [Z] @a, @b;'
https://docs.raku.org/language/operators#index-entry-[]_(reduction_metaoperators)
https://docs.raku.org/language/operators#index-entry-hyper_method_call_operator
https://docs.raku.org/routine/flat
答案4
使用 GNU sed 的扩展正则表达式模式来简化正则表达式的编写,我们的方法是在模式空间中随时维护两行。然后将上一行的倒数第二个字段移至当前行末尾。
sed -E '
1s/$/,/
$!N
s/(,[^,]+)(,[^,]*\n.*)/\2\1/
P;D
' file
输入:-
10-04-2022 00:39:13,36707,1455008753,32
11-05-2022 00:39:13,36708,1555008753,26
21-05-2022 00:39:13,36708,1555408753,15
12-06-2022 00:39:13,36709,1655008753#
输出:-
10-04-2022 00:39:13,36707,1455008753,
11-05-2022 00:39:13,36708,1555008753,32
21-05-2022 00:39:13,36708,1555408753,26
12-06-2022 00:39:13,36709,1655008753#,15