我想反转文本文件(或stdin)中的行顺序,保留每行的内容。
因此,从以下内容开始:
foo
bar
baz
我希望最后
baz
bar
foo
是否有用于此的标准UNIX命令行实用程序?
我想反转文本文件(或stdin)中的行顺序,保留每行的内容。
因此,从以下内容开始:
foo
bar
baz
我希望最后
baz
bar
foo
是否有用于此的标准UNIX命令行实用程序?
以下是著名的sed技巧:
# reverse order of lines (emulates "tac")
# bug/feature in HHsed v1.5 causes blank lines to be deleted
sed '1!G;h;$!d' # method 1
sed -n '1!G;h;$p' # method 2
(说明:在保留缓冲区、交换缓冲区和保留缓冲区之前准备非初始行,在末尾打印输出行)
或者(以更快的执行速度)从awk一行代码:
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file*
如果你记不住了,
perl -e 'print reverse <>'
在具有GNU实用程序的系统上,其他答案更简单,但并不是所有的世界都是GNU/Linux。。。
我真的很喜欢“尾巴-r”的答案,但我最喜欢的呆呆的答案是。。。。
gawk '{ L[n++] = $0 }
END { while(n--)
print L[n] }' file
$ (tac 2> /dev/null || tail -r)
试试tac,它在Linux上运行,如果不起作用,可以使用tail-r,它在BSD和OSX上运行。
编辑下面生成从1到10的随机排序的数字列表:
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') **...**
其中点被替换为实际命令,该命令反转列表
tac
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') \
<(tac)
python:在sys.stdin上使用[::-1]
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') \
<(python -c "import sys; print(''.join(([line for line in sys.stdin])[::-1]))")
Just Bash:)(4.0+)
function print_reversed {
local lines i
readarray -t lines
for (( i = ${#lines[@]}; i--; )); do
printf '%s\n' "${lines[i]}"
done
}
print_reversed < file
最简单的方法是使用tac命令。tac是猫的逆。例子:
$ cat order.txt
roger shah
armin van buuren
fpga vhdl arduino c++ java gridgain
$ tac order.txt > inverted_file.txt
$ cat inverted_file.txt
fpga vhdl arduino c++ java gridgain
armin van buuren
roger shah
对于可能在shell脚本中使用tac的跨操作系统(即OSX、Linux)解决方案,如上文所述,使用自制程序,然后将tac别名如下:
安装lib
对于MacOS
brew install coreutils
对于linux debian
sudo apt-get update
sudo apt-get install coreutils
然后添加别名
echo "alias tac='gtac'" >> ~/.bash_aliases (or wherever you load aliases)
source ~/.bash_aliases
tac myfile.txt
你可以用vim-stdin和stdout来实现。您也可以使用ex来兼容POSIX。vim只是ex的视觉模式。事实上,您可以将ex与vim-e或vim-e(改进的ex模式)一起使用。vim很有用,因为与sed等工具不同,它缓冲文件以供编辑,而sed用于流。您可能可以使用awk,但必须手动缓冲变量中的所有内容。
其目的是:
从stdin读取对于每一行,将其移至第1行(反向)。命令为g/^/m0。这意味着对于每一行g;匹配行的开头,它匹配任何^;将其移到地址0之后,即第1m0行。打印所有内容。命令为%p。这意味着所有行的范围为%;打印行p。强制退出而不保存文件。命令是q!。这意味着退出q;用力!。
# Generate a newline delimited sequence of 1 to 10
$ seq 10
1
2
3
4
5
6
7
8
9
10
# Use - to read from stdin.
# vim has a delay and annoying 'Vim: Reading from stdin...' output
# if you use - to read from stdin. Use --not-a-term to hide output.
# --not-a-term requires vim 8.0.1308 (Nov 2017)
# Use -E for improved ex mode. -e would work here too since I'm not
# using any improved ex mode features.
# each of the commands I explained above are specified with a + sign
# and are run sequentially.
$ seq 10 | vim - --not-a-term -Es +'g/^/m0' +'%p' +'q!'
10
9
8
7
6
5
4
3
2
1
# non improved ex mode works here too, -e.
$ seq 10 | vim - --not-a-term -es +'g/^/m0' +'%p' +'q!'
# If you don't have --not-a-term, use /dev/stdin
seq 10 | vim -E +'g/^/m0' +'%p' +'q!' /dev/stdin
# POSIX compliant (maybe)
# POSIX compliant ex doesn't allow using + sign to specify commands.
# It also might not allow running multiple commands sequentially.
# The docs say "Implementations may support more than a single -c"
# If yours does support multiple -c
$ seq 10 | ex -c "execute -c 'g/^/m0' -c '%p' -c 'q!' /dev/stdin
# If not, you can chain them with the bar, |. This is same as shell
# piping. It's more like shell semi-colon, ;.
# The g command consumes the |, so you can use execute to prevent that.
# Not sure if execute and | is POSIX compliant.
seq 10 | ex -c "execute 'g/^/m0' | %p | q!" /dev/stdin
如何使其可重复使用
我使用一个我称为ved的脚本(vim编辑器,如sed)来使用vim编辑stdin。将其添加到路径中名为ved的文件中:
#!/usr/bin/env sh
vim - --not-a-term -Es "$@" +'%p | q!'
我使用的是一个+命令,而不是+'%p'+'q!',因为vim将您限制为10个命令。因此,合并它们可以让“$@”有9个以上的命令,而不是8个。
然后您可以执行以下操作:
seq 10 | ved +'g/^/m0'
如果您没有vim 8,请将其改为:
#!/usr/bin/env sh
vim -E "$@" +'%p | q!' /dev/stdin
如果要就地修改文件,可以运行
sed -i '1!G;h;$!d' filename
这样就不需要创建临时文件,然后删除或重命名原始文件,并具有相同的结果。例如:
$tac file > file2
$sed -i '1!G;h;$!d' file
$diff file file2
$
根据埃菲米恩特的回答,这几乎做到了,但不是完全做到了我想要的。
我看到了很多有趣的想法。但试试我的主意。用管道将文本输入到:
rev|tr'\n“~”| rev|tr“~”\n“
它假定字符“~”不在文件中。这应该适用于1961年的每一个UNIX shell。或者类似的东西。
碰巧我想高效地获取一个非常大的文本文件的最后n行。
我尝试的第一件事是tail-n 10000000 file.txt>ans.txt,但我发现它非常慢,因为tail必须查找到位置,然后返回打印结果。
当我意识到这一点时,我切换到另一个解决方案:tac file.txt | head-n 10000000>ans.txt。这一次,搜索位置只需要从末端移动到所需位置,它节省了50%的时间!
带回家消息:
如果尾部没有-r选项,请使用tac-file.txt | head-n n。
不确定我是否错过了什么。用管子分类怎么样
即cat文件|排序-r
对不起,如果我错过了这个问题的要点。我经常用它来扫描系统日志。
在linux中:观看“tail/var/log/syslog |排序-r”
希望它能帮助某人最美好的祝福