UNIX(私の場合はCygwin)ソートユーティリティを使用してソートしようとしている固定幅フィールドファイルがあります。
問題は、ファイルの上部に2行のヘッダーがあり、ファイルの下部にソートされていることです(各ヘッダー行がコロンで始まるため)。
並べ替えに「最初の2行を並べ替えずに渡す」、またはコロン行を先頭に並べ替える順序を指定する方法があります-残りの行は常に6桁の数字で始まります(実際にはキーIそれが役立つ場合は、「ソート中」です。
例:
:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
500123TSTMY_RADAR00
222334NOTALINEOUT01
477821USASHUTTLES21
325611LVEANOTHERS00
ソートする必要があります:
:0:12345
:1:6:2:3:8:4:2
010005TSTDOG_FOOD01
222334NOTALINEOUT01
325611LVEANOTHERS00
477821USASHUTTLES21
500123TSTMY_RADAR00
(head -n 2 <file> && tail -n +3 <file> | sort) > newfile
括弧はサブシェルを作成し、stdoutをラップして、単一のコマンドから来たかのようにパイプまたはリダイレクトできるようにします。
awk
の使用を気にしない場合は、awk
の組み込みパイプ機能を利用できます。
例えば。
extract_data | awk 'NR<3{print $0;next}{print $0| "sort -r"}'
これは、最初の2行を逐語的に出力し、残りをsort
にパイプします。
これには、パイプ入力の一部を選択的にソートできるという非常に特有の利点があることに注意してください。提案されている他のすべての方法は、複数回読み取ることができるプレーンファイルのみをソートします。これは何でも動作します。
パイプされたデータで動作するバージョンは次のとおりです。
(read -r; printf "%s\n" "$REPLY"; sort)
ヘッダーに複数の行がある場合:
(for i in $(seq $HEADER_ROWS); do read -r; printf "%s\n" "$REPLY"; done; sort)
この解決策は here
tail -n +3 <file> | sort ...
を使用できます(tailはファイルの内容を3行目から出力します)。
head -2 <your_file> && nawk 'NR>2' <your_file> | sort
例:
> cat temp
10
8
1
2
3
4
5
> head -2 temp && nawk 'NR>2' temp | sort -r
10
8
5
4
3
2
1
コードは2行だけで済みます...
head -1 test.txt > a.tmp;
tail -n+2 test.txt | sort -n >> a.tmp;
数値データの場合、-nが必要です。アルファソートの場合、-nは必要ありません。
サンプルファイル:
$ cat test.txt
ヘッダ
8
5
100
1
-1
結果:
$ cat a.tmp
ヘッダ
-1
1
5
8
100
単純な場合、sed
は仕事をエレガントに行うことができます。
your_script | (sed -u 1q; sort)
または同等に、
cat your_data | (sed -u 1q; sort)
キーは1q
にあり、最初の行(ヘッダー)を出力して終了します(入力の残りをsort
に残します)。
与えられた例では、2q
がトリックを行います。
-u
スイッチ(バッファなし)は、そうでなければ入力をチャンクで読み取るsed
s(特にGNU)に必要です。そのため、代わりにsort
を通過したいデータを消費します。
そのため、引数がソートとまったく同じであるbash関数があります。サポートファイルとパイプ。
function skip_header_sort() {
if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then
local file=${@: -1}
set -- "${@:1:$(($#-1))}"
fi
awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file
}
使い方。この行は、少なくとも1つの引数があり、最後の引数がファイルであるかどうかを確認します。
if [[ $# -gt 0 ]] && [[ -f ${@: -1} ]]; then
これにより、ファイルが別の引数に保存されます。最後の引数を消去しようとしているので。
local file=${@: -1}
ここで最後の引数を削除します。ソート引数として渡したくないので。
set -- "${@:1:$(($#-1))}"
最後に、awkの部分を実行し、引数(ファイルの場合は最後の引数を引いたもの)を渡してawkでソートします。これは元々Daveによって提案され、ソート引数を取るように修正されました。パイピングしている場合は$file
が空になるため、無視されます。
awk -vsargs="$*" 'NR<2{print; next}{print | "sort "sargs}' $file
コンマ区切りファイルの使用例。
$ cat /tmp/test
A,B,C
0,1,2
1,2,0
2,0,1
# SORT NUMERICALLY SECOND COLUMN
$ skip_header_sort -t, -nk2 /tmp/test
A,B,C
2,0,1
0,1,2
1,2,0
# SORT REVERSE NUMERICALLY THIRD COLUMN
$ cat /tmp/test | skip_header_sort -t, -nrk3
A,B,C
0,1,2
2,0,1
1,2,0
これはIan Sherbinの答えと同じですが、私の実装は:-
cut -d'|' -f3,4,7 $arg1 | uniq > filetmp.tc
head -1 filetmp.tc > file.tc;
tail -n+2 filetmp.tc | sort -t"|" -k2,2 >> file.tc;
以下は、他の回答から派生したbashシェル関数です。ファイルとパイプの両方を処理します。最初の引数はファイル名、または標準入力の場合は「-」です。残りの引数はソートに渡されます。いくつかの例:
$ hsort myfile.txt
$ head -n 100 myfile.txt | hsort -
$ hsort myfile.txt -k 2,2 | head -n 20 | hsort - -r
シェル機能:
hsort ()
{
if [ "$1" == "-h" ]; then
echo "Sort a file or standard input, treating the first line as a header.";
echo "The first argument is the file or '-' for standard input. Additional";
echo "arguments to sort follow the first argument, including other files.";
echo "File syntax : $ hsort file [sort-options] [file...]";
echo "STDIN syntax: $ hsort - [sort-options] [file...]";
return 0;
Elif [ -f "$1" ]; then
local file=$1;
shift;
(head -n 1 $file && tail -n +2 $file | sort $*);
Elif [ "$1" == "-" ]; then
shift;
(read -r; printf "%s\n" "$REPLY"; sort $*);
else
>&2 echo "Error. File not found: $1";
>&2 echo "Use either 'hsort <file> [sort-options]' or 'hsort - [sort-options]'";
return 1 ;
fi
}
Pythonの場合:
import sys
HEADER_ROWS=2
for _ in range(HEADER_ROWS):
sys.stdout.write(next(sys.stdin))
for row in sorted(sys.stdin):
sys.stdout.write(row)