在小猫问题和在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。现在,它不能再匹配as,但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。这就是我们的代码应该如何表现吗?