我有一个很大的文件,如下所示:
esup_255_3 transdecoder 7655 8192
esup_6093_1 transdecoder 2732 2774
esup_25727_1 transdecoder 1 60
...
列3和4表示数字间隔。
我尝试修改此文件,以使区间内包含的数字列表在不同的列中列出(此处为第5列),如下所示:
esup_255_3 transdecoder 7655 8192 7655
esup_255_3 transdecoder 7655 8192 7656
esup_255_3 transdecoder 7655 8192 7657
esup_255_3 transdecoder 7655 8192 ...
esup_255_3 transdecoder 7655 8192 8192
esup_6093_1 transdecoder 2732 2774 2732
esup_6093_1 transdecoder 2732 2774 2733
esup_6093_1 transdecoder 2732 2774 ....
esup_6093_1 transdecoder 2732 2774 2774
... and so on...
我认为Perl可能会对此有所帮助,但我对它还很陌生,我只精通bash,在这里我似乎找不到正确的方法来获得我需要的东西。
1条答案
按热度按时间jexiocij1#
像这样的东西?
当我在你的代码片段上运行它时,它会打印出641行:
下面是说明。让我们从选项开始:
-e
(“execute”或“evaluate”)只是告诉Perl命令行上的下一个内容是要运行的代码,因此它不会在标准输入中查找代码。-n
告诉它自动地逐行迭代它的输入;就好像有一个while (<>) {
...}
循环包裹着实际的代码。在循环体中,当前行位于主题变量$_
中。-l
告诉它从输入中去掉换行符,并自动为每个打印出的字符串添加一个换行符;这基本上消除了图片中的换行符并简化了逻辑。因此,程序将逐行读取输入,并在每一行上运行作为
-e
的参数给出的代码。让我们看看这段代码,它以下面的语句开头:正则表达式没有显式的字符串进行匹配,因此它自动匹配当前行所在的
$_
。(因为^
在开头,$
在结尾)。由于最外面的括号,实际的行值也会被捕获,因此它将是匹配返回的第一个项,其被分配给变量$line
。行的第一部分可以是任何内容(因为
.*
匹配所有内容),所以我们真正关注的是字符串结束的方式,而不是开始的方式。(\s
),它的作用是确保我们不会遗漏以下任何一个数字。(\d+
),括号中捕获了它,因此该值也将由匹配返回;这是第二次捕获,因此它进入赋值中的第二个变量$from
。在这些数字之后,我们查找更多的空格(至少需要一个空格字符,但允许任何数字),后面是另一个数字序列;第二组数字将再次被捕获并返回,因此它将在最后一个变量$to
中结束。最后,我们允许在最后一组数字后面跟随任意数量的可选尾随空格。因此,在阅读第一行
$_ = "esup_255_3 transdecoder 7655 8192 "
之后,match +赋值语句会将$line
设置为整个字符串的副本,将$from
设置为7655
,将$to
设置为8192
。然后我们来看看输出。这一行:
这是撰写此循环的简短方式:
这意味着它循环从
$from
到$to
的所有数字,重用$_
作为循环控制变量(这就是为什么我们必须将当前行复制到$line
中)。对于范围内的每个值,它打印出整个行的副本,后跟一个制表符和当前数字。