有没有办法向表添加换行符以创建子组?

有没有办法向表添加换行符以创建子组?

我很难弄清楚如何表达这一点,所以 Google-fu 失败了。

我有一个带有数据表的文本文件。我想插入换行符以在视觉上分隔子组。

例如,如果我从以下内容开始:

jan   ford
jan   trillian
mar   trillian
sep   marvin

第一个字段是我的子组字段,那么输出应该是:

jan   ford
jan   trillian

mar   trillian

sep   marvin

我可以做一些事情,比如^(a-z){3}\t(.*)\n\1\t(.*)$识别月份相同的两条线,但我不知道当它们不同时如何匹配。

理想情况下,我希望这是一个可以放入 BBedit 的正则表达式,但我对其他解决方案持开放态度。

答案1

它看起来像是bbedit某种付费的 OSX 编辑器。恐怕我从未使用过它,也无法安装它,所以我无法为您提供帮助。根据您显示的正则表达式,它有自己的正则表达式语法,因此您不太可能在使用它的通用 *nix 站点上找到解决方案。但是,这里还有其他一些选择。在这两种情况下,想法都是保存第一个字段,如果它与上一行中看到的不同,则打印一个空行:

$ awk '{if($1!=last && NR>1){print ""}last=$1;}1;' file
jan ford
jan trillian

mar trillian

sep marvin

awk是一种脚本语言,旨在处理基于字段的数据。它会自动将每一行分割成字段,然后可以将其称为$1, $2... $N。因此,上面的脚本将保存变量中的第一个字段last,并且对于除第一行之外的每一行(这就是意思),如果与当前保存的值不同,NR>1它将打印一个空行。 lastawk1;是“打印每一行”的简写。

或者,您也可以在以下位置执行此操作perl

$ perl -lape '$F[0] ne $last && $.>1 && print ""; $last=$F[0]' file
jan ford
jan trillian

mar trillian

sep marvin

在这里,我们使用perl命令行开关来完成大部分工作。 make-aperl作用类似于awk将每个输入行拆分到数组中@F。因此,$F[0]是第一个字段。使每个调用添加一个换行符-l,因此只打印一个空行。使其在应用 给出的脚本后打印每个输入行。该脚本本身与上面的脚本完全相同。perlprintprint ""-p-eawk

答案2

awk 'NR > 1 && $1 != last {print ""}; {print; last = $1}'

答案3

既然你可以匹配重复者,那么你就会想要否定你的行为。你可以这样做:

sed -e'/^\n/!{$n;G;N;s/^\(\(...\).*\)\n\2/\1\2/;}' -eP\;D <in >out

换句话说,从双倍行距文件开始,并删除组之间的第二个空格。

针对您的示例输入打印运行该命令:

jan   ford
jan   trillian

mar   trillian

sep   marvin

这实际上让我向你提出一个问题:我想我明白特里莉安在平行宇宙中可能有两个生日,但是你能解释一下为什么你认为马文可能有一个生日吗?不过我想九月比较合适——总是阴沉的。


这是另一张,礼貌@don_crissti(如果稍作修改):

sed -etD -e'$q;N;/^\(...\).*\n\1/!s/\n/&&/;:D' -eP\;D

我更喜欢他的。他一开始问我:为什么要编辑掉换行符而不只是编辑它们?我真的没有任何答案,而且大多是矛盾的,因为我认为这不会产生太大的影响。

但问题是,这里使用的先行技术需要一个刀刃缓冲区——如果缓冲区一次增长到大于当前的两条输入线,它可能会报告误报。当您实际上还将换行符插入到您匹配的同一流中并且要求您可以轻松区分已插入的输入行或需要插入的行时,平衡单行先行会变得更加困难读。这种平衡需要至少每个周期进行一次额外的测试 - 我通过了/^\n/!上面的测试。

但该sed机制的一个非常基本的部分是s///替换语句的tested return,它在成功时执行条件分支。因为他的替换总是生成额外的行,所以当模式空间被删除并且est 仍然在脚本顶部工作时sed,行循环(这就是清除test 的返回)不会翻转。通过这种方式,don 可以非常简单地对每次插入进行 est 测试,并在下一次迭代的顶部可靠地评估上一次迭代的结果。Dtt

因此,请对他的答案之一投赞成票,因为我猜他不会将其放在这里。


Get 命令将的保留空间追加到插入的ewline 分隔符sed之后的模式空间。\n不过,这里从来没有使用过保留空间,所以剩下的G就是\newline。

ext命令将 ext 输入行N附加N到模式空间中插入的\newline 分隔符之后。对每个输入行执行Get 然后Next 会得到\n每个输入行两条 ewlines 。

相关内容