awkを使用して列を並べ替える


12

私はcsvファイルの7列目を最後に移動しようとしています

awk -F '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}',OFS= "$file"

$ fileはディレクトリ内の.csvファイルです。ただし、出力は

awk:                          ^ syntax error

誰でもこのエラーを修正する方法を知っていますか?


7
awkエラーを表示するときは、すべてを表示する必要があります。^エラーが発生しましたコマンドの特定の部分を示しています。
テルドン

回答:


10

-Fオプションには引数が必要です。-F,たとえば。

awkスクリプトの最後は、残りのパラメーターとともに(スペース文字)で区切る必要があります。

フィールド区切り文字が,あり、それを保持したい場合、および列の数が一定で11以下の場合、これを試してください:

awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"

8
@anuribsでは、これを許可するプログラムはほとんどありません。標準的な方法はcommand file > newfile && mv newfile fileです。とはいえ、awkこれをサポートするGNUの新しいバージョンは次のとおりgawk -i inplace '{blah blah}' fileです。
テルドン

1
代わりに、代わりにmv newfile file使用することができますcat newfile > file ; rm -f newfile-これはのinodeとパーミッションを保持しfileます。
cas

通常、mktemp一時ファイル名をスクリプトにハードコーディングするのではなく、使用することをお勧めします。例tf=$(mktemp) ; command file > "$tf" ; cat "$tf" > file ; rm -f "$tf"
cas

7

より短い解決策は

awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file

,+すべてのawkバージョンで動作するかどうかは-cわかりませんが、少なくともGNU awkで動作し、互換性モードでも動作します。

説明:

  • $(NF+1)=$7:最初に、行の最後に7番目のフィールドを追加します($12=$7この場合も可能です)
  • $7="":次のステップで7番目のフィールドが消去されます(ただし、周囲の区切り文字はそのままです)
  • 区切り文字を削除するには$0=$0、複数のコンマをフィールド区切り文字として処理することにより(-F',+'ここで+は1回以上)、レコード全体を再設定し($1=$1以前の出力フィールドを使用して強制的に行を再構築する)セパレーター(オプションで設定-v OFS=,
  • すべてのシャッフルが完了したら、結果を印刷する準備ができました 1

入力例:

1,2,3,4,5,6,7,8,9,10,11

出力

1,2,3,4,5,6,8,9,10,11,7

他の列が空白の場合はどうなりますか?しかし、はい、FSはPOSIXの正規表現です(複数文字の場合)ので、動作する,+はずです。
Random832

(1)入力データの7番目の列を「nappear」に設定するだけでなく、nullに設定することは、この問題の難しい部分であることを理解しています。しかし、Random832が言うように、ソリューションは空白の列を壊します(例えばall,ball,call,,,fallall,ball,call,fall)。(2)  $(NF+1)=$7は賢いアプローチです。私見$0 = $0 OFS $7は、少し明確で、数文字だけ長く、同じことをしているようです。$0 = $0 OFS $7あなたのコードと同じことをしない状況を考えることができますか?
G-Manが「Reinstate Monica」と言う

@ Random832 @ G-Manはい、空白フィールド、空白行、NF <7などのエッジケースは個別に処理するか、コードを再配置する必要があります。これは単なるアイデアであり、すべての一般的な場合の「完全な解決策」ではなく、明確なはずです。$0=$0 OFS $7はおそらくに同じですが$(NF+1)=$7、一般的にはコードの残りの部分が変更されていないだけです。
-jimmij

5

で印刷しているOFS=ので、フィールド間にセパレータがない場合は、値を$7変数に保存し、$7空に設定して行と変数を直接印刷できます。すべてのフィールドを指定する必要はありません。

$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file 
12345687

3

あなたはおそらく意味する:

awk -F, -v OFS='' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' "$file"

awk単一引用符が表示されないことを知っていOFS=''ますか?同様に入力することもできOFS=ます。それはまったく同じです。
ワイルドカード

1
はい、わかりました。ただし、ぶら下がりの割り当ては嫌いです。
マイケルVehrs 16


3

あなたは、特にあなたがawkを使用していたと言っていなかった、とあなたはなかったあなたがが提供するように、インプレース編集を使用したいと言うsed -iので、ここで、あるsed -i変種。通常awk、列の操作には適していますが、これはsed自然に任意の数の列を処理するため、私が好むケースの1つです。

MOVECOL=7
N=$((MOVECOL-1))
sed -r -e "s/^(([^,]*,){$N})([^,]*),(.*)/\1\4,\3/" -i test.csv

説明:

  • -r 拡張された正規表現を選択して、バックスラッシュの多くを回避します
  • 最初のグループは、カンマで終了する文字列の$ N回の繰り返し、言い換えると、移動したいものの前の列で、最後のカンマがあります
  • 2番目のグループは$ N番目の繰り返しで、忘れてしまいます
  • 3番目のグループは、最後のコンマなしで移動する列です
  • 4番目のグループは、移動する列の後のすべての列で構成され、前にコンマはありません
  • 最初のグループ、最後のグループ、抽出した列に置き換え、必要に応じてコンマを挿入します。

もちろん、これは引用符でコンマを隠す(または、さらに悪いことにエスケープする)ファイルでは機能しませんが、いくつかの深刻なアクロバットがなければ、awkはそれを処理しません。あなたはその問題を持っている場合は、とほうが良いと思いますperlモジュールText:CSVまたはpythonモジュールcsv


2

いくつかのawkバリアント(ファイルが変数内にあると仮定$file

  • ここで、すべての列を循環させ、フィールド区切り記号(OFS)を使用して印刷し、行末にレコードターミネーター(ORS)を印刷できます。

    awk  -F',' -v OFS=,                                \
    '{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
    printf "%s",$7;printf ORS}' "$file"
  • ここで正規表現とgensub()関数を使用して

    gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"

    殺害 7 番目のフィールドを、行の末尾に、それを印刷。

    • $0 全記録です
    • $nn 番目のレコードです
    • NF 現在の行のフィールド数です
    • OFS 出力フィールド区切り文字
    • ORS 出力レコードターミネータ
    • 1これは、awk trueにデフォルト($0)を出力するように指示するトリックです。

更新 ...

ほとんど忘れてしまいますが、7 番目の列に続くすべての列をシフトすることは可能です。

awk  -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"

(1)おそらく、OFS $7より堅牢です"," $7。(2)", " $7OPがコンマの後にスペースを必要としないことを質問が示す限り、それは間違っていると思います。(そして、入力されたデータは、その後、コンマの後にスペースがあった場合は$7、既にスペースで始まります、そしてあなたは、余分なものを追加することと思います。)
G-マンが「回復モニカ言う

@ G-Manいくつかのアイデア、いくつかのバリエーションを提案することが主な目的でした。おかげで、スポットについては、私はOFS $7、より堅牢であるだけでなく、より一般的であることに同意します(「速攻は無駄になります」
ヘイスター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.