Linuxでファイルの最後の列を削除する方法


25

txtファイルの最後の列を削除したいのですが、列番号がわかりません。どうすればこれができますか?

例:

入力:

1223 1234 1323 ... 2222 123
1233 1234 1233 ... 3444 125
0000 5553 3455 ... 2334 222

そして、出力を次のようにします。

1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

それから、例とあなたの期待出力を追加this..please行うには多くの方法があります...
heemayl

@heemayl OK私はやった
ザラ

ありがとう..列タブは区切られていますか、スペースで区切られていますか?
heemayl

@heemaylスペースはデリミネーター
ザラ

回答:


43

awk

awk 'NF{NF-=1};1' <in >out

または:

awk 'NF{NF--};1' <in >out

または:

awk 'NF{--NF};1' <in >out

これはブードゥー教のように見えますが、機能します。これらのawkコマンドにはそれぞれ3つの部分があります。

最初はでNF、これは2番目の部分の前提条件です。NF行内のフィールドの数を含む変数です。AWKでは、0でも空の文字列でもない場合は真です""。したがって、2番目の部分(NF減少する部分)NFは0でない場合にのみ発生します。

2番目の部分(NF-=1 NF--または--NF)は、NF変数から1を減算するだけです。これは、フィールドを変更する場合(この場合は最後のフィールドを削除する)、awk再構築し$0、デフォルトでスペースで区切られたすべてのフィールドを連結するため、最後のフィールドが印刷されないようにします。$0もう最後のフィールドが含まれていません。

最後の部分は1です。それは魔法ではなく、を意味する表現として使用されているだけtrueです。場合はawkそれに関連する行為のない真の表現評価し、awkデフォルトのアクションですprint $0


@JJoao:ああ、ありがとう、忘れてしまった--。注、現在、;1POSIX準拠が必要です。
cuonglm

私の最初の本能はforループを使用することですが、これははるかに簡潔で賢い方法です。
セルギーKolodyazhnyy

5
デフォルト以外の区切り文字を使用している場合は、いくつかの変更を加える必要があることに注意してください。,あなたの区切り記号と仮定:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
Mr. Llama

1
NFの減少の効果はPOSIXによる未定義の動作です-実行しているawkに応じて異なる出力が得られます。必要に応じて最後のフィールドを削除するawksもあれば、何もしないものもあれば、構文エラーなどを報告するものもあります。
エド・モートン

16

grepPCREでの使用:

$ grep -Po '.*(?=\s+[^\s]+$)' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

GNUの使用sed

$ sed -r 's/(.*)\s+[^\s]+$/\1/' file.txt 
1223 1234 1323 ... 2222
1233 1234 1233 ... 3444
0000 5553 3455 ... 2334

1
@ramin Sure .. 新しい質問として質問してください(これがこのサイトの仕組みです):)
heemayl

@ramin時間制限や警告はありますか?
-heemayl

これは標準的な問題ではないと言っています!
ザラ

@ramin Ok ..管理者に連絡させてください。彼らがあなたを助けてくれるかもしれません。質問が既に質問され、回答されている可能性..
heemayl

3
Linuxでファイル名を変更するにはどうすればよいですか」のような基本的な質問をしないでください。Googleを使用します。
クリストファーハンマルストローム

11

Perlの使用:

perl -lane '$,=" ";pop(@F);print(@F)' in

rev+ を使用cut

rev in | cut -d ' ' -f 2- | rev

5

GNU sedの使用:

sed -r 's/\s+\S+$//' input.txt

より一般的には、これはOSXのBSD sedとGNU sedで動作します:

sed 's/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//' input.txt

1

区切り文字が常に単一の文字である場合(2つ以上の連続する区切り文字が空のフィールドを指定する場合)、head入力ファイルの最初の行だけを区切り、区切り文字をカウントし(n区切り文字はフィールドの数を意味しますn+1cut1stフィールドからの印刷に使用できますまでn番目のフィールド(最後の2番目)、例えばタブ区切りの入力を持ちます:

n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l)
cut -f1-$n infile > outfile

または、csvファイルの場合:

n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l)
cut -d, -f1-$n infile > outfile

時間があれば、いくつかのベンチマークを実行しますが、膨大な入力があると、このソリューションは正規表現を使用する他のソリューションよりも速くなるはずです。cutこのジョブ用に最適化されたフィールドを使用します。


1

次のいずれかを使用できます。

sed 's/[[:space:]]*[^[:space:]]*$//' file

awk '{sub(/[[:space:]]*[^[:space:]]*$/,"")}1' file

0

vimの使用:

vimでファイルを開く

vim <filename> 

カーソルが他の場所に置かれた場合に備えて、最初の行に移動します。

gg

「q」という名前のマクロを作成します qqは現在の行$の最後に移動し、最後のスペースF(大文字のF、リテラルSPACE)に戻り、現在の位置から行末まで削除Dして次の行に移動jします。でマクロの記録を停止しqます。

qq$F Djq

これで@q、各行に対してマクロを繰り返すことができます。
を押し@@て最後のマクロを繰り返したり、さらに簡単にすることもできます。

99@q

マクロを99回繰り返します。
注:番号は行と正確に一致してはなりません。


0

同様の問題を抱えているが、フィールドセパレータが異なる場合、このawkメソッドはフィールドセパレータを正しく保持します。

$ cat file 
foo.bar.baz
baz.bar.foo
$ awk -F'.' 'sub(FS $NF,x)' file
foo.bar
baz.bar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.