在第一行X行之后排序文件的更优雅的方法是什么?

时间:2015-01-05 23:48:41

标签: bash sorting

我今天在Stack Overflow上做了很多寻找解决方案,并且在跳过X行之后发现了很多关于排序的问题,但没有真正的通用答案,所以我把自己的方法放在一起这样:

head -n 15 FILE.EXT > temp.txt
tail -n+16 FILE.EXT | sort >> temp.txt
mv temp.txt FILE.EXT

这将对文件进行排序(选择排序选项),同时保留前15行的顺序。这显然是相当不优雅的,有三个文件引用和两个不同的值要输入。理想情况下,如果可能的话,我想提出一个不那么繁琐的命令,因为这似乎是一个非常普遍的愿望而没有太大的支持。

  • 有没有人比我的解决方案更简单?
  • 我做了什么有什么不对吗?潜在问题?
  • 这个问题更适合使用脚本,但是我的命令仍然可能比创建和执行一次性脚本的速度快一些。

我甚至不接近一个bash专家,所以我希望有一些bash-fu可以使这个快速单行。有没有办法在单个命令中创建和引用变量,以便用户只需要输入名称和行号等内容?

3 个答案:

答案 0 :(得分:6)

这个'one-liner'生成输出:

awk 'NR <= 15 { print; next } { print | "sort" }'

干净地覆盖原始文件更难,通常涉及写入临时文件的内容,并在完成时重命名。

作为sputnick points out,如果您拥有GNU awk,则可以使用-i选项进行就地覆盖:

gawk -i 'NR <= 15 { print; next } { print | "sort" }' FILE.EXT

(而且gawk通常也会安装为awk。)

如果你没有GNU awk,那么我有一个来自Kernighan&amp; amp;的脚本ow的脚本overwrite。派克The UNIX Programming Environment就是这么做的。

用法:

ow FILE.EXT awk 'NR <= 15 { print; next } { print | "sort" }' FILE.EXT

代码:

:   "@(#)$Id: ow.sh,v 1.6 2005/06/30 18:14:08 jleffler Exp $"
#
#   Overwrite file
#   From: The UNIX Programming Environment by Kernighan and Pike
#   Amended: remove PATH setting; handle file names with blanks.

case $# in
0|1)    
    echo "Usage: $0 file command [arguments]" 1>&2
    exit 1;;
esac

file="$1"
shift
new=${TMPDIR:-/tmp}/ovrwr.$$.1
old=${TMPDIR:-/tmp}/ovrwr.$$.2

trap "rm -f '$new' '$old' ; exit 1" 0 1 2 15

if "$@" >"$new"
then
    cp "$file" "$old"
    trap "" 1 2 15
    cp "$new" "$file"
    rm -f "$new" "$old"
    trap 0
    exit 0
else
    echo "$0: $1 failed - $file unchanged" 1>&2
    rm -f "$new" "$old"
    trap 0
    exit 1
fi

这是旧代码;我现在已经修改了近十年,但我已经使用了很多。如noted Charles Duffy那样,如果您可能面对以破折号开头的文件名(因为那些可能会被误认为是cp或{的命令行选项,它可以用于一些现代化{1}}),它应该有一个shebang线等等。

它还显示了捕获信号(尽管如今,我通常陷阱'mv',相当于'0 1 2 3 13 15')并命名临时文件以防止偶然干扰(使用EXIT HUP INT QUIT PIPE TERM而非$$ - 就像我说的那样,这是旧代码。)

答案 1 :(得分:2)

你可以做一个在文件开头跳过一些行的排序,如下所示:

 { head -n 15 && sort; } < file > tempfile

它有效,因为head在15行后停止读取,所以sort会看到文件的其余部分。

所以要解决完整的原始问题。

{ head -n 15 && sort; } < file > tempfile && mv tempfile file

答案 2 :(得分:0)

怎么样:

 { head -n 15 file; tail -n+16 file | sort ; }