首页 文章

如何反转文件中的行顺序?

提问于
浏览
517

我想颠倒文本文件(或标准输入)中行的顺序,保留每行的内容 .

所以,即从以下开始:

foo
bar
baz

我想结束

baz
bar
foo

是否有标准的UNIX命令行实用程序?

20 回答

  • 2

    BSD尾巴:

    tail -r myfile.txt
    

    参考:FreeBSDNetBSDOpenBSDOS X手册页 .

  • 133

    另外值得一提的是:tac(咳嗽,反转 cat ) . 部分coreutils .

    将一个文件翻转到另一个文件中

    tac a.txt > b.txt
    
  • 363

    well-known sed tricks

    # 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
    

    (说明:在非初始行前加上保持缓冲区,交换行和保持缓冲区,在末尾打印出行)

    或者(执行速度更快)from the awk one-liners

    awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file*
    

    如果你不记得了,

    perl -e 'print reverse <>'
    

    在具有GNU实用程序的系统上,其他答案更简单,但并非全世界都是GNU / Linux ...

  • 0

    如果你碰巧在 vim 使用

    :g/^/m0
    
  • -5
    $ (tac 2> /dev/null || tail -r)
    

    试试 tac ,它适用于Linux,如果不起作用,请使用 tail -r ,它适用于BSD和OSX .

  • 34
    tac <file_name>
    

    例:

    $ cat file1.txt
    1
    2
    3
    4
    5
    
    $ tac file1.txt
    5
    4
    3
    2
    1
    
  • 3

    请尝试以下命令:

    grep -n "" myfile.txt | sort -r -n | gawk -F : "{ print $2 }"
    
  • 38

    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
    
  • 12

    最简单的方法是使用 tac 命令 . taccat 的反面 . 例:

    $ 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
    
  • 52

    我真的很喜欢“尾巴”答案,但我最喜欢的gawk答案是....

    gawk '{ L[n++] = $0 } 
      END { while(n--) 
            print L[n] }' file
    
  • 10

    在你的命令结束时: | tac

    tac完全符合您的要求,它“将每个文件写入标准输出,最后一行写入 . ”

    tac与cat相反:-) .

  • 2

    最佳方案:

    tail -n20 file.txt | tac
    
  • 15

    EDIT 以下生成从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: using [::-1] on sys.stdin

    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]))")
    
  • 10

    对于可能在shell脚本中使用 tac 的跨操作系统(即OSX,Linux)解决方案,如上所述,使用自制程序,那么就像这样使用别名:

    brew install coreutils
    echo "alias tac='gtac'" >> ~/.bash_aliases (or wherever you load aliases)
    source ~/.bash_aliases
    tac myfile.txt
    
  • 2

    这适用于BSD和GNU .

    awk '{arr[i++]=$0} END {while (i>0) print arr[--i] }' filename
    
  • 22

    我有同样的问题,但我也希望第一行( Headers )保持在最顶层 . 所以我需要使用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

    你可以用 vim stdinstdout 来做到这一点 . 您也可以使用 exPOSIX compliant . vim 只是 ex 的可视模式 . 实际上,您可以将 exvim -evim -E (改进的 ex 模式)一起使用 . vim 非常有用,因为与 sed 之类的工具不同,它会缓冲文件以进行编辑,而 sed 则用于流 . 您可能可以使用 awk ,但您必须手动缓冲变量中的所有内容 .

    我们的想法是做以下事情:

    • 从标准输入读取

    • 对于每一行,将其移至第1行(反转) . 命令是 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
    

    How to make this reusable

    我使用一个脚本我调用 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
    
  • 0

    tail -r 诀窍:

    seq 1 20 |尾巴-r

  • 1194

    使用Visual Studio™,您可以使用鼠标选择底线 . '切断'这条线,然后'粘贴'到顶部 . 继续这样做,直到原始顶行位于底部 . 我相信这种方法适用于其他编辑器,但我没有尝试过 .

  • 0
    sort -r < filename
    

    要么

    rev < filename
    

相关问题