实施“ TAC”:从文件反向打印行


30

小猫问题在U&L看到有关sed魔术的问题之间,如何实施tac


目的

实现一个程序,该程序将反转并打印文件中的行。


输入值

作为名称或通过标准输入提供的文件


输出量

线颠倒了,以标准输出。


计分

源代码字节。


9
tac对于尾随换行有点奇怪。它将a\nb\n(尾随换行)转换为b\na\na\nb(不尾随换行)转换为 ba\n。这就是我们的代码应该如何表现吗?
丹尼斯


10
另外,如果我们必须复制tac的行为,执行3字节的Bash答案tac只是时间问题……
Dennis 2015年

1
此时,@ Dennis最好保持未定义状态。
尼克·T

1
@丹尼斯对我有意义。将文件行可视化为水平行,所有行均以结尾\ntac反转这些行的顺序。如果\n从文件的中间删除了,则终止的行将连接到下一行,但是对于最后一行,则没有下一行要连接。
Blacklight Shining 2015年

Answers:


15

GS2,3个字节

* +

这三个字节依次是分割线,反向线和连接线。


9

Perl,11个字节

$\=$_.$\}{

行为完全一样tac。此代码需要-p切换,我将其计为1个字节。

试运行

$ echo -en 'a\nb' | perl -pe'$\=$_.$\}{' | xxd -g 1
0000000: 62 61 0a                                         ba.
$ echo -en 'a\nb\n' | perl -pe'$\=$_.$\}{' | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

怎么运行的

如所解释这里,所述-p开关基本上包裹while (<>) { ... ; print }程序周围,所以源代码等价于

 while(<>)
 {
   $\ = $_ . $\
 }
 print

对于每行输入,我们在当前行($_)之前添加$\(最初是未定义的),并用结果更新后者。

处理print完所有行后,打印局部变量的值$_(在此范围内未定义),然后输出输出记录分隔符($\)。


关心解释这是如何工作的吗?
xebtl

2
@xebtl邪恶。添加-p开关将您的代码包装在一个开始while(<>){和结束的循环中} continue { print },允许仅通过修改过滤输入$_$\=$_.$\将每行输入添加到输出记录终止符,并提前终止}{perl提供的while块,因此continue不再将该块连接到该块。因此,所有输入行都以$\相反的顺序添加,然后continue { print }最终运行,最后打印“ nothing”($_输入结束后为undef),但终止符为$\
hobbs 2015年

@xebtl grr,在反斜杠和反引号彼此靠近的地方,注释中的代码格式似乎有点破损。也许您能猜出我想说的话。
hobbs 2015年

1
@primo第一个示例显示在这种情况下会发生什么。输出将是奇怪的,但与tac完全一样。
丹尼斯

1
@Dennis第18页,这本书
msh210 '16

8

Pyth,4个字节

j_.z

.z是输入,以行分隔为列表,_将其反转j并由一个字符连接,默认情况下为\n



7

视网膜,7字节

!rm`.*$

使用单个正则表达式,Retina可以在“匹配”模式下运行。通常,这只是打印匹配项的数量,但通过!我们配置它来打印实际的匹配项(由换行分隔)。

实际的正则表达式仅仅是.*$.*匹配任何行(可能为空),因为.可以匹配除换行符之外的任何字符。我待会儿到$

我们如何使其反向打印比赛?通过使用.NET的从右到左匹配模式,该模式由激活r。这意味着正则表达式引擎在查找匹配项时从字符串的末尾开始,然后向后工作。

最后,m使$匹配项成为的结尾而不是字符串的结尾。为什么我们甚至需要那个?问题是.*生成无关的匹配。考虑正则表达式替换

s/a*/$0x/

应用于输入baaababaa。您会认为这样会产生收益baaaxbaxbaax,但实际上能给您收益baaaxxbaxxbaaxx。为什么?因为匹配后aaa,引擎的光标位于a和之间b。现在,它不能再匹配as,但a*也对空字符串感到满意。这意味着,在每场比赛之后,您都会得到另一个空比赛。

我们在这里不希望这样,因为它会引入额外的空行,因此我们通过要求匹配包括末尾的内容来丢弃那些无关的匹配项(由于从右到左模式,它们位于行的开头)线。


6

Haskell,34个字节

main=interact$concat.reverse.lines

[编辑]

通过更换保存一个字节unlinesconcat




4

Befunge-93,17个字节

~:1+!#v_
>:#,_@>$

这里没什么好看的;只需将所有内容放入堆栈,然后将其弹出即可。


4

纯Bash(无外部公用程序),56

mapfile a
for((i=${#a[@]};i--;));{
printf %s "${a[i]}"
}

tac正如Dennis的评论所要求的那样,这是进行精确仿真的少数答案之一:

$ echo -en 'a\nb' | ./tacemu.sh | xxd -g 1
0000000: 62 61 0a                                         ba.
$ echo -en 'a\nb\n' | ./tacemu.sh | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.
$ 



4

JavaScript(SpiderMonkey Shell),38个字节

[...read(readline())].reverse().join``

很简单


read() 读取文件

readline() 从STDIN读取一个字符串

[...str]str分成一个char数组

reverse() 将反转数组

join`` 将数组整理为字符串



4

C#,179171字节

using B=System.Console;class A{static void Main(){var a=new System.Collections.Stack();string b;while((b=B.ReadLine())!=null)a.Push(b);foreach(var c in a)B.WriteLine(c);}}

读取行,将它们放在堆栈中,然后向后写入。我会为此使用Mathematica,但是它没有EOF的意义。


3

sed,9个字节

1!G;h;$!d

无需支持,这是著名的sed单线。


10
如果不是您自己的工作,我建议您制作答案社区Wiki。
lirtosiast 2015年


3

Powershell,41个字节

$a=$args|%{gc $_};[array]::Reverse($a);$a

将文件的内容逐行存储在中a,取反a,最后打印出来。



3

滑稽,6字节

ln<-uN

ln分割行,<-反转行,合并uN行和格式以获取原始输出。


3

重击,48 43个字符

(灵感来自Digital TraumaBash答案。对此想法的支持应该归他所有。)

mapfile -c1 -C's=$2$s;set'
printf %s "$2$s"

样品运行:

bash-4.3$ echo -en 'a\nb' | bash tac.sh | xxd -g 1
0000000: 62 61 0a                                         ba.

bash-4.3$ echo -en 'a\nb\n' | bash tac.sh | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

我认为您可以mapfile -c1 -Cf代替mapfile -c1 -Cf a
Digital Trauma 2015年

正确。同时我也发现了它,只是先尝试​​了一些棘手的问题-C
manatwork

3

GNU Awk,27个字符

(受埃德·莫顿Ed Morton)的GNU Awk答案启发。CW,因为我不想劫持他的解决方案。)

{s=$0RT s}END{printf"%s",s}

请注意,通过更改RT→ ,它将RS变为可移植的标准Awk,但失去了保留最终换行符的功能。

样品运行:

bash-4.3$ echo -en 'a\nb' | awk '{s=$0RT s}END{printf"%s",s}' | xxd -g 1
0000000: 62 61 0a                                         ba.

bash-4.3$ echo -en 'a\nb\n' | awk '{s=$0RT s}END{printf"%s",s}' | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

您可以删除“%s”
ninjalj 2015年

@ninjalj,仅当我们可以假定输入将永远不包含“%”时。
manatwork

3

SNOBOL,42个字节

S S =INPUT CHAR(10) S :S(S)
 OUTPUT =S
END

2

Gema,25个字符

*\n=@set{s;$0${s;}}
\Z=$s

样品运行:

bash-4.3$ echo -en 'a\nb' | gema '*\n=@set{s;$0${s;}};\Z=$s'
ba

bash-4.3$ echo -en 'a\nb\n' | gema '*\n=@set{s;$0${s;}};\Z=$s'
b
a


2

sed,7个字节

G;h;$!d

这对我有用(这是其他地方最短的解决方案),但是我真的不想找出原因。在发现这个问题之前,我只是弄混了著名的9字节技巧。我猜G第一行什么都没有?


2
实际上可以做些事情:您的代码在输出的末尾产生了一个额外的换行符。(G将换行符和保留空间的内容追加到模式空间。尽管将空的保留空间的内容附加为确实无害,但仍附加换行符。)
manatwork 2015年

2

JavaScript(Node.js),91字节

console.log(require('fs').readFileSync(process.argv[2])+"".split(d="\n").reverse().join(d))

您是说console.log((require('fs').readFileSync(process.argv[2])+"").split(d="\n").reverse().join(d))(92字节)吗?您当前的代码不会颠倒这行。
牙刷

2

Bash +通用工具,25

tr \\n ^G|rev|tr ^G \\n|rev

这里^G是一个文字BEL字符。我假设输入仅是可打印的ascii。

tr通过用BELS替换换行符ansforms整个输入到一行,然后reverses该行,然后transforms回多,然后rev再次erses的每一行,以获得所需的输出。


2

MATLAB,44岁

@(x) strjoin(fliplr(strsplit(x,'\n')),'\n');

在新行处分割字符串,翻转结果数组,然后以新行字符重新加入。


2

朱莉娅,65个字节

open(s->print(join(reverse([l for l=readlines(s)]),"")),ARGS[1])

这将文件作为命令行参数,并以相反的顺序打印其行。尾随的换行符移到最前面,这与tac合法的不同。

取消高尔夫:

function p(s::Stream)
    # Create a vector of the lines of the input stream
    L = [l for l in readlines(s)]

    # Reverse the vector and join it back into a string
    j = join(reverse(L), "")

    # Print the string to STDOUT
    print(j)
end

# Open the file specified in the first command line argument
# and apply the function p to its contents
open(p, ARGS[1])

2

,3 + 2 = 5字节

使用rn标志;从标准输入读取。

RVg

r标志的读标准输入,并将其存储在行的列表g(其通常的命令行AR的列表或多个)。然后,我们反转该列表,并自动打印该列表。该n标志使列表以换行符作为分隔符输出。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.