テキストファイルの行から特定の単語を削除する方法は?


13

テキストファイルは次のようになります。

Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341

ここでLiquid penetration 95% mass (m)、値のみを取得するために行から削除します。どうすればいいですか?


3
単にgrep -o '[^[:space:]]\+$' file
アビナッシュRaj

@AvinashRaj:現時点では、このソリューションは
パテメダル

2
@ pa4080少なくともテストした入力(10M行)については、PCREを使用することにより、Avinash Rajの一般的なアプローチを1桁高速にすることができます。(GNU grepのが受け入れるように私は、エンジン、ないパターンは、責任があることを確認できた\S+$のいずれかで-E-P。)この種のソリューションが本質的に低速ではありませんので。しかし、私はまだあなたのベンチマーク獲得したαғsнιηのcut方法に近い場所でそれを得ることができません。
エリアケイガン

回答:


22

=サインが1つしかない場合は、次のようにすべてを削除できます=

$ sed -r 's/.* = (.*)/\1/' file
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

元のファイルを変更する-i場合は、テスト後にオプションを使用します。

sed -ri 's/.* = (.*)/\1/' file

ノート

  • -r私たちは脱出する必要はありませんので、EREを使用(し、)
  • s/old/new置き換えるoldnew
  • .* 任意の数の任意の文字
  • (things)保存thingsして後に後方参照に\1\2など

それが働いてくれてありがとう。次のコマンドを使用して、既存のファイルを上書きしました:sed -i -r 's /.*=(。*)/ \ 1 /' time.txt
OE

後方参照を回避しないのはなぜですか?s/^.*= //正しい値は行末にあるため、同様にうまく機能します。
17

@jpaughまあ、部分的に、それは最初のものが掲載された私の答え変更するには遅すぎだから-他の人がすでにこのような場合のために、あなたが言及ソリューションおよび他のより効率的な方法を与えられた:)しかし、おそらく使用する方法を示している\1などの人々のためのいくつかの値を持っている人検索時にこの質問に答える、そんな単純な問題がない人
-Zanna

@Zanna少なくとももっと一般的です。
jpaugh

21

これはawk;のための仕事です。値が最後のフィールドでのみ発生すると仮定します(例に従って):

awk '{print $NF}' file.txt
  • NFawk変数であり、レコード(行)内のフィールドの数に展開されるため、$NF$前に注意してください)最後のフィールドの値が含まれます。

例:

% cat temp.txt 
Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341

% awk '{print $NF}' temp.txt
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

13

ここにリストされているさまざまなソリューションを比較することにしました。この目的のために、OPが提供するコンテンツに基づいて大きなファイルを作成しました。

  1. 次の名前の単純なファイルを作成しましたinput.file

    $ cat input.file
    Liquid penetration 95% mass (m) = 0.000205348
    Liquid penetration 95% mass (m) = 0.000265725
    Liquid penetration 95% mass (m) = 0.000322823
    Liquid penetration 95% mass (m) = 0.000376445
    Liquid penetration 95% mass (m) = 0.000425341
    
  2. 次に、このループを実行しました。

    for i in {1..100}; do cat input.file | tee -a input.file; done
    
  3. 端末ウィンドウがブロックされました。killall tee別の端末から実行しました。次に、コマンドでファイルの内容を調べました:less input.fileおよびcat input.file。最後の行を除いて、見栄えが良かった。そこで、最後の行を削除し、バックアップコピーを作成しましたcp input.file{,.copy}inplaceオプションを使用するコマンドのため)。

  4. ファイルへの行の最終カウントinput.file2 192 473です。コマンドでその番号を取得しましたwc

    $ cat input.file | wc -l
    2192473
    

比較の結果は次のとおりです。

  • grep -o '[^[:space:]]\+$'

    $ time grep -o '[^ [:space:]] \ + $' input.file> output.file
    
    実数0m58.539s
    ユーザー0m58.416s
    sys 0m0.108s
    
  • sed -ri 's/.* = (.*)/\1/'

    $ time sed -ri 's /.* =(。*)/ \ 1 /' input.file
    
    実数0m26.936s
    ユーザー0m22.836s
    sys 0m4.092s
    

    あるいは、出力を新しいファイルにリダイレクトする場合、コマンドはより高速になります。

    $ time sed -r 's /.* =(。*)/ \ 1 /' input.file> output.file
    
    実数0m19.734s
    ユーザー0m19.672s
    sys 0m0.056s
    
  • gawk '{gsub(".*= ", "");print}'

    $ time gawk '{gsub( "。* ="、 ""); print}' input.file> output.file
    
    実際の0m5.644s
    ユーザー0m5.568s
    sys 0m0.072s
    
  • rev | cut -d' ' -f1 | rev

    $ time rev input.file | カット-d '' -f1 | rev> output.file
    
    実際の0m3.703s
    ユーザー0m2.108s
    sys 0m4.916s
    
  • grep -oP '.*= \K.*'

    $ time grep -oP '。* = \ K. *' input.file> output.file
    
    実際の0m3.328s
    ユーザー0m3.252s
    sys 0m0.072s
    
  • sed 's/.*= //' (それぞれ、この-iオプションはコマンドを数倍遅くします)

    $ time sed 's /.*= //' input.file> output.file
    
    実際の0m3.310s
    ユーザー0m3.212s
    sys 0m0.092s
    
  • perl -pe 's/.*= //' (この-iオプションでは、ここでの生産性に大きな違いは生じません)

    $ time perl -i.bak -pe 's /.*= //' input.file
    
    実際の0m3.187s
    ユーザー0m3.128s
    sys 0m0.056s
    
    $ time perl -pe 's /.*= //' input.file> output.file
    
    実際の0m3.138s
    ユーザー0m3.036s
    sys 0m0.100s
    
  • awk '{print $NF}'

    $ time awk '{print $ NF}' input.file> output.file
    
    実際の0m1.251s
    ユーザー0m1.164s
    sys 0m0.084s
    
  • cut -c 35-

    $ time cut -c 35- input.file> output.file
    
    実際の0m0.352s
    ユーザー0m0.284s
    sys 0m0.064s
    
  • cut -d= -f2

    $ time cut -d = -f2 input.file> output.file
    
    実際の0m0.328s
    ユーザー0m0.260s
    sys 0m0.064s
    

アイデアの源。


2
そう、私のcut -d= -f2解決策は勝ちます。(笑)
αғsнιη

このファイルの作成方法に関する詳細を教えてください。また、wc -l3つの数値をどのように出力しますか?他のオプションが渡されない場合、-lオプションは行数以外のすべてを抑制する必要があります。
エリアケイガン

@EliahKagan、できました。答えを更新しました。
pa4080

ああ、そうですね。スペースは数字グループの区切り文字でした。(wc実際にこれらのスペースが表示されていましたか?それを行うロケール設定はありますか?)更新してくれてありがとう!
エリアケイガン

@EliahKagan:最後にwcもう1回の質問を読みました。私の知恵が今日どこにあるのかはわかりませんが、本当に理解できませんでした。実際、スペースは数字グループの区切り文字でありwc、それらを追加しません:)
pa4080

12

grep-Pを有するためPCRE(ASパターンを解釈P erl- C ompatible R egular E XPRESSION)と-o一致したパターンのみを印刷します。\Kマッチした部分は、それ自体の前に来無視されます通知します。

$ grep -oP '.*= \K.*' infile
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

または、cut代わりにコマンドを使用できます。

cut -d= -f2 infile

2
pa4080のベンチマークでテストされたすべてのメソッドの中で最速で実行したことに加えて、この回答cutメソッド、より少ないメソッドをテストし、より大きな入力ファイルを使用した小さなベンチマークでも明確な勝者でした。私が個人的に好きな方法の高速版よりも10倍以上も高速でした(そして、私の答えは主に)。
エリアケイガン


6

を使用してファイルのコンテンツを反転し、区切り文字としてスペースを使用し、ターゲットフィールドとして1 revを使用cutして出力をパイプし、元の数値を取得するために再度反転します。

$ rev your_file | cut -d' ' -f1 | rev
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341

5

これはシンプルで、短く、簡単に記述、理解、および確認できます。私は個人的に気に入っています。

grep -oE '\S+$' file

grepUbuntuでは-Eまたは-Pで呼び出されると、空白文字(実際には通常はスペースまたはタブ)を意味し、そうでないものを意味するために省略形 \sを取ります。使用数量詞行末アンカーをパターンは、行の末尾に1つ以上の非ブランクと一致します。の代わりに使用できます。この場合の意味は同じですが、異なる正規表現エンジンが使用されるため、パフォーマンス特性が異なる場合があります\S+$\S+$-P-E

これは、Avinash Rajのコメント付きソリューションと同等です(簡単でコンパクトな構文を使用するだけです)。

grep -o '[^[:space:]]\+$' file

これらのアプローチは、数字のに末尾の空白がある可能性がある場合は機能しません。それらは変更することができますが、ここで説明する意味はありません。それはより多くのケースの下での作業に解決策を一般化するために、時には有益ですが1が通常知る方法がないので、それは、ほぼ同じ頻度の人々が想定する傾向があるので、そうすることは現実的ではありません多くの異なる互換性のない方法のどちらに問題が最終的に必要になることがありますが一般化されます。


パフォーマンスは重要な考慮事項である場合があります。この質問は、入力が非常に大きいことを規定するものではなく、ここに投稿されたすべてのメソッドが十分に高速である可能性があります。ただし、速度が必要な場合は、1,000万行の入力ファイルに関する小さなベンチマークを次に示します。

$ perl -e 'print((<>) x 2000000)' file > bigfile
$ du -sh bigfile
439M    bigfile
$ wc -l bigfile
10000000 bigfile
$ TIMEFORMAT=%R
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
819.565
$ time grep -oE '\S+$' bigfile > bigfile.out
816.910
$ time grep -oP '\S+$' bigfile > bigfile.out
67.465
$ time cut -d= -f2 bigfile > bigfile.out
3.902
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
815.183
$ time grep -oE '\S+$' bigfile > bigfile.out
824.546
$ time grep -oP '\S+$' bigfile > bigfile.out
68.692
$ time cut -d= -f2 bigfile > bigfile.out
4.135

順序が重要な場合(I / Oが重いタスクの場合と同じように)、および結果を歪める可能性のある他の処理をバックグラウンドで実行していないマシンがなかったため、2回実行しました。これらの結果から、少なくとも暫定的に、使用したサイズの入力ファイルについて、以下を結論づけます。

  • うわー!渡す-P(使用にPCRE)ではなく-G(何も方言が指定されていないデフォルト)または-E作られたgrep桁を超えることにより、より速く。そのため、大きなファイルの場合、上記のコマンドよりもこのコマンドを使用した方がよい場合があります。

    grep -oP '\S+$' file
  • ワオ!!cut方法αғsнιηの答えは、より迅速な私の方法のさらに高速なバージョンよりも一桁を超えています!これはpa4080のベンチマークでも勝者であり、これはこれよりも多くのメソッドをカバーしましたが、入力は小さく、他のすべてのメソッドのうち、テストに含めるために選択しました。パフォーマンスが重要な場合やファイルが巨大な場合は、αғsнιηの方法を使用する必要があります。cut -d= -f2 filecut

    これはまた、リマインダとして機能シンプルcutかつpasteユーティリティを忘れてはならない、と該当する場合、おそらく優先されなければならない、などのより高度なツールがあってもgrepそれは多くの場合、最初の行のソリューションとして提供されている(と私は個人的にもっと慣れていていること使用する)。


4

perl- S ubstituteパターン/.*= /空の文字列を持ちます//

perl -pe 's/.*= //' input.file > output.file
perl -i.bak -pe 's/.*= //' input.file
  • からperl --help

    -e program        one line of program (several -e's allowed, omit programfile)
    -p                assume loop like -n but print line also, like sed
    -i[extension]     edit <> files in place (makes backup if extension supplied)
    

sed -パターンを空の文字列に置き換えます:

sed 's/.*= //' input.file > output.file

または(ただし上記よりも遅い)

sed -i.bak 's/.*= //' input.file
  • これは、Zannaの回答にあるものよりも数倍速いため、このアプローチに言及しています

gawk-パターン".*= "を空の文字列に置き換えます""

gawk '{gsub(".*= ", "");print}' input.file > output.file
  • からman gawk

    gsub(r, s [, t]) For each substring matching the regular expression r in the string t,
                     substitute the string s, and return the number of substitutions. 
                     If t is not supplied, use $0...
    
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.