在小猫问题和在U&L看到有关sed
魔术的问题之间,如何实施tac
?
目的
实现一个程序,该程序将反转并打印文件中的行。
输入值
作为名称或通过标准输入提供的文件
输出量
线颠倒了,以标准输出。
计分
源代码字节。
tac
只是时间问题……
\n
。tac
反转这些行的顺序。如果\n
从文件的中间删除了,则终止的行将连接到下一行,但是对于最后一行,则没有下一行要连接。
在小猫问题和在U&L看到有关sed
魔术的问题之间,如何实施tac
?
实现一个程序,该程序将反转并打印文件中的行。
作为名称或通过标准输入提供的文件
线颠倒了,以标准输出。
源代码字节。
tac
只是时间问题……
\n
。tac
反转这些行的顺序。如果\n
从文件的中间删除了,则终止的行将连接到下一行,但是对于最后一行,则没有下一行要连接。
Answers:
$\=$_.$\}{
行为完全一样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
完所有行后,打印局部变量的值$_
(在此范围内未定义),然后输出输出记录分隔符($\
)。
-p
开关将您的代码包装在一个开始while(<>){
和结束的循环中} continue { print }
,允许仅通过修改过滤输入$_
。$\=$_.$\
将每行输入添加到输出记录终止符,并提前终止}{
perl提供的while
块,因此continue
不再将该块连接到该块。因此,所有输入行都以$\
相反的顺序添加,然后continue { print }
最终运行,最后打印“ nothing”($_
输入结束后为undef),但终止符为$\
。
!rm`.*$
使用单个正则表达式,Retina可以在“匹配”模式下运行。通常,这只是打印匹配项的数量,但通过!
我们配置它来打印实际的匹配项(由换行分隔)。
实际的正则表达式仅仅是.*$
。.*
匹配任何行(可能为空),因为.
可以匹配除换行符之外的任何字符。我待会儿到$
。
我们如何使其反向打印比赛?通过使用.NET的从右到左匹配模式,该模式由激活r
。这意味着正则表达式引擎在查找匹配项时从字符串的末尾开始,然后向后工作。
最后,m
使$
匹配项成为行的结尾而不是字符串的结尾。为什么我们甚至需要那个?问题是.*
生成无关的匹配。考虑正则表达式替换
s/a*/$0x/
应用于输入baaababaa
。您会认为这样会产生收益baaaxbaxbaax
,但实际上能给您收益baaaxxbaxxbaaxx
。为什么?因为匹配后aaa
,引擎的光标位于a
和之间b
。现在,它不能再匹配a
s,但a*
也对空字符串感到满意。这意味着,在每场比赛之后,您都会得到另一个空比赛。
我们在这里不希望这样,因为它会引入额外的空行,因此我们通过要求匹配包括末尾的内容来丢弃那些无关的匹配项(由于从右到左模式,它们位于行的开头)线。
qN/W%N*
读取标准输入,打印到标准输出。
说明:
q Get input.
N/ Split at newlines.
W% Reverse list.
N* Join with newlines.
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.
$
import sys;print''.join(sys.stdin.readlines()[::-1])
import sys;print sys.stdin.read()[::-1]
呢
$a=$args|%{gc $_};[array]::Reverse($a);$a
将文件的内容逐行存储在中a
,取反a
,最后打印出来。
(灵感来自Digital Trauma的Bash答案。对此想法的支持应该归他所有。)
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
。
-C
。
(受埃德·莫顿(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.
use IO;func main(){c=File.readLines(args[0]);for(x=c.length-1;x>=0; println(c[x--]))0;
看到这里展开
for
语法将其缩短很多。在此处
G;h;$!d
这对我有用(这是其他地方最短的解决方案),但是我真的不想找出原因。在发现这个问题之前,我只是弄混了著名的9字节技巧。我猜G
第一行什么都没有?
G
将换行符和保留空间的内容追加到模式空间。尽管将空的保留空间的内容附加为确实无害,但仍附加换行符。)
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])
tac
对于尾随换行有点奇怪。它将a\nb\n
(尾随换行)转换为b\na\n
和a\nb
(不尾随换行)转换为ba\n
。这就是我们的代码应该如何表现吗?