我想反转文本文件(或stdin)中的行顺序,保留每行的内容。
因此,即从:
foo
bar
baz
我想结束
baz
bar
foo
为此有标准的UNIX命令行实用程序吗?
我想反转文本文件(或stdin)中的行顺序,保留每行的内容。
因此,即从:
foo
bar
baz
我想结束
baz
bar
foo
为此有标准的UNIX命令行实用程序吗?
Answers:
brew install coreutils(gtac默认安装为)安装tac 。
echo -n "abc\ndee" > test; tac test。
有著名的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 ...
tail -rtac。
tac应该处理不适合内存的任意大文件(尽管行长仍然受限制)。尚不清楚sed解决方案是否适用于此类文件。
在命令末尾输入:
| tac
tac完全满足您的要求,它“将每个文件写入标准输出,最后一行。”
tac与cat :-)相反。
tac命令的值,这对于可能最终搜索同一主题的新用户很有用。
如果您碰巧正在vim使用中
:g/^/m0
$ (tac 2> /dev/null || tail -r)
试试tac,它在Linux上有效,如果不起作用,请使用tail -r,它在BSD和OSX上有效。
tac myfile.txt-我想念什么?
tail -r以防万一tac无法使用。tac不符合POSIX。都不是tail -r。仍然不是万无一失,但这可以提高工作的几率。
tac可用,会发生什么,但会用完RAM,并在消耗大量输入流的过程中进行交换。它失败,然后tail -r成功处理剩余的流,并给出错误的结果。
brew install coreutils 并使用它gtac来代替tactac作为别名gtac(例如,如果您想要一个跨平台使用它的shell脚本(Linux,OSX))
尝试以下命令:
grep -n "" myfile.txt | sort -r -n | gawk -F : "{ print $2 }"
sed 's/^[0-9]*://g'
nl默认情况下将无法为空行编号。该-ba选项在某些系统上可用,不是通用的(HP / UX出现在我的脑海中,尽管我希望不是),而grep -n它将始终对与(在此例中为空)正则表达式匹配的每一行进行编号。
cut -d: -f2-
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
-nenenenenenene并见证人们建议始终使用printf '%s\n'而不是的原因echo。
最简单的方法是使用tac命令。tac是cat的逆。例:
$ 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
我真的很喜欢“ tail -r ”答案,但是我最喜欢的gawk答案是...。
gawk '{ L[n++] = $0 }
END { while(n--)
print L[n] }' file
mawk在Ubuntu 14.04 LTS上进行过测试-可以正常运行,因此它不是特定于GNU AWK的。+1
n++可以替换为NR
编辑 以下内容将生成一个随机排序的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]))")
对于可能使用的跨OS(即OSX,Linux)解决方案 tac在shell脚本中使用的如上面其他人所述,请使用自制程序,然后使用别名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
最佳解决方案:
tail -n20 file.txt | tac
对于Emacs用户:(C-x h选择整个文件),然后单击M-x reverse-region。也仅适用于选择零件或线并将其还原。
我有同样的问题,但我也希望第一行(标题)保持在最前面。所以我需要使用awk的力量
cat dax-weekly.csv | awk '1 { last = NR; line[last] = $0; } END { print line[1]; for (i = last; i > 1; i--) { print line[i]; } }'
PS也可以在cygwin或gitbash中使用
1\n20\n19...2\n而不是20\n19...\2\n1\n。
您可以使用vim stdin和进行操作stdout。您还可以使用ex要符合POSIX标准。vim只是的视觉模式ex。事实上,你可以使用ex带有vim -e或vim -E(改进的ex模式)。
vim之所以有用,是因为sed与之类似的工具不同,它缓冲文件以供编辑,而sed用于流。您也许可以使用awk,但是必须手动将所有内容缓冲在变量中。
该想法是要执行以下操作:
g/^/m0。这意味着对于每一行都是全局的g;匹配行的开头,匹配任何内容^;将其移到地址0(第1行)之后m0。%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,请ved改为输入:
#!/usr/bin/env sh
vim -E "$@" +'%p | q!' /dev/stdin
rev
text here
要么
rev <file>
要么
rev texthere
sort -r < filename
要么
rev < filename
sort -r仅在输入已经排序的情况下才有效,在此情况下不是这样。rev反转每行的字符,但保持行序不变,这也不是Scotty要求的。因此,这个答案实际上根本没有答案。
perl -e 'print reverse <>'但它可能也适用于其他方法)。