私は以下を試していますが、運がありません。
SORT_BY='-k3,3r -k2,2 -k1,1r'
awk 'NR<4{print $0;next}{print $0 | sort '"${SORT_BY}"' -t"~"}'
いろいろな引用、引用解除などを試しましたが、いつもawkに問題があります。
awk: illegal statement
延長はどのようにしますか>
答え1
awkはシェルではありません。sort
CプログラムからUNIXツールを直接呼び出せないように、awkから直接UNIXツールを呼び出すことはできません。
これにより、目的の操作が機能します。
SORT_BY='-k3,3r -k2,2 -k1,1r'
awk 'NR<4{print; next} {print | "sort -t\"~\" '"${SORT_BY}"'"}'
しかし、これが良いアイデアかどうかは不明です。
ソートされていない3行のヘッダー行を印刷してから、残りのデータをソートしたい場合はおそらく最良の方法です。 awks 出力区切り文字を設定し、入力区切り文字を同じ文字でソートすることに加えて、ソートから awk を完全に分離し、シェルを生成するために awk を必要とせず、入力を 2 回開く必要がないため、入力がパイプで出てくるかファイルから出ても動作します。
sep='~'
awk -v OFS="$sep" '{print (NR>3), NR, $0}' file |
sort -t "$sep" -k1,1n -k2,2n -k5,5r -k4,4 -k3,3r |
cut -d "$sep" -f3-
答え2
変数は、一重引用符で囲まれた文字列内では拡張されません。この問題を解決する方法はありません。
この例では、データの最初の3行をそのまま出力し、残りはソートしようとしています。簡単に保つためにこれを行います
sort_opts=( -k3,3r -k2,2 -k1,1r )
{ head -n 3 file
awk 'NR > 3' file | sort "${sort_opts[@]}" -t '~' } >newfile
内部で並べ替えたい場合、スペースを最初の文字として使用して同じままであると仮定するawk
場合:$IFS
sort_opts=( -k3,3r -k2,2 -k1,1r )
awk -v sort_opts="${sort_opts[*]}" '
BEGIN { sortcmd = sprintf("sort %s -t \"~\"", sort_opts) }
NR <= 3 { print; next } { print | sortcmd }' file >newfile
これはawk
コマンドラインで使用するソートオプションを提供し、ブロックは変数で文字列として使用するソートコマンドを生成し、最後のブロックでそれを使用します(行4から始まりトリガされます)。-v
BEGIN
sortcmd
print
in でパイプと共に使用される場合、awk
パイプの右側はパイプされるシェルコマンドを表す文字列でなければなりません。あなたのコードではそうではないので、「違法宣言」エラーが発生します。
取得する必要がある値にawk
バックスラッシュが含まれている場合は、代わりに環境変数を使用できます(各バックスラッシュが2倍になるのを防ぐため)。
sort_opts=( -k3,3r -k2,2 -k1,1r )
SORT_OPTS="$sort_opts[*]" awk '
BEGIN { sortcmd = sprintf("sort %s -t \"~\"", ENVIRON["SORT_OPTS"]) }
NR <= 3 { print; next } { print | sortcmd }' file >newfile