0

您好,我正在尝试在 perl( 或 ruby​​ ) 中创建一个单行程序,它将文件中的数据读取到数组中,并在第 10 个元素之后用换行符将其打印在列中。

文件是这样的

Name
Course1
Mark1
Course2
Mark2
Course3
Mark3
Course4
Mark4

并且应该像这样显示

Name   Course1  Mark1   Course2   Mark2   Course3   Mark3   Course4   Mark4

这是我尝试过的

perl -ne '@a=split"\n",$_;print join("\t"=>splice@a,0,10)' Data.txt 
4

4 回答 4

5

这不起作用,因为当您一次读取一行时,您会在换行符上进行拆分。你需要-0777让它工作。

您也只打印前 10 个元素,因此您需要引入一个循环。

perl -0777nE'@F = split /\n/; say join "\t", splice @F,0,10 while @F' Data.txt 

那乞求利用-a

perl -F'\n' -0777naE'say join "\t", splice @F,0,10 while @F' Data.txt 

或者我们可以采取完全不同的方法。简短而甜蜜:

perl -pe's/\n/\t/ if $. % 10' Data.txt

如果不是 10 列的倍数,则将以尾随制表符而不是换行符结尾。好吧,不太好。那么怎么样

perl -0777pe's/\n(?!\z)/ ++$i % 10 ? "\t" : "\n" /eg' Data.txt

更新您已经更改了您的问题以请求固定宽度的字段。

如果您事先知道宽度(例如字段之间的 10 + 2 个字符 = 12):

perl -F'\n' -0777naE'say pack "(A12)9 A*", splice @F,0,10 while @F' Data.txt 

如果您不这样做:

perl -MList::Util=max -F'\n' -0777naE'
   $w = 2 + max map length, @F;
   say pack "(A$w)9 A*", splice @F,0,10 while @F;
' Data.txt 
于 2013-04-24T23:38:03.647 回答
2
ruby -e 'ARGF.map{|l|l.strip}.each_slice(10) {|a| puts a.join "\t"}' Data.txt
于 2013-04-24T23:47:31.067 回答
0

ikegami打败了我。但无论如何我都会发布我的。

perl -pe 'tr/\n/\t/ if $. % 9 != 0'

编辑:啊,更好。谢谢ikegami(对于$.,我忘了那个)。

于 2013-04-24T23:44:04.507 回答
0

数据样本只有 9 行,因此无法方便地放入 10 行存储桶中。我添加了一个占位符,所以我的文本文件如下所示:

姓名
课程1
标记1
课程2
标记2
课程3
标记3
课程4
马克4
-----
姓名
课程1
标记1
课程2
标记2
课程3
标记3
课程4
马克4
-----

我会在 Ruby 中按照以下方式进行操作:

puts ARGF.lines.map(&:chomp).each_slice(10).map{ |a| a.join(' ') }

这给了我这样的输出:

名称 Course1 Mark1 Course2 Mark2 Course3 Mark3 Course4 Mark4 -----
名称 Course1 Mark1 Course2 Mark2 Course3 Mark3 Course4 Mark4 -----

使用制表符代替空格是微不足道的:替换' '"\t",但如何留给读者练习。

map(&:chomp)去除尾随的行尾,以便在打印时字段可以存在于一行中。each_slice(10)一次抓取十个数组元素,这会产生一个数组数组,每个子数组包含十个字符串。最后map{ |a| a.join(' ') }用空格或制表符连接子数组(如果更改为"\t". 或者,可以使用a * ' 'ora * "\t"代替join,但join更常用。

于 2013-04-25T02:47:18.437 回答