web-dev-qa-db-ja.com

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

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

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)を削除して、値のみを取得します。どうすればいいですか?

13
O.E

=記号が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/newoldnewに置き換えます
  • .*任意の数の任意の文字
  • (things)thingsを保存して、後で\1\2などで後方参照します。
22
Zanna

これは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
22
heemayl

grep および PCRE を持つための-Pを使用(パターンをPerl-C互換性RegularExpression)および-oは、一致したパターンのみを印刷します。 \K通知は、一致する部分がそれより前に来ることを無視します。

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

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

cut -d= -f2 infile
13
αғsнιη

ここにリストされているさまざまなソリューションを比較することにしました。この目的のために、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.fileへの行の最終カウントは2 192 473です。コマンドwcでその番号を取得しました:

    $ cat input.file | wc -l
    2192473
    

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

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

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

     $ time sed -ri 's /.* =(。*)/\1 /' input.file 
     
     real 0m26.936s 
     user 0m22。 836s 
     sys 0m4.092s 
    

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

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

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

     $ time rev input.file | cut -d '' -f1 | rev> output.file 
     
     real 0m3.703s 
     user 0m2.108s 
     sys 0m4.916s 
    
  • grep -oP '.*= \K.*'

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

     $ time sed 's /.*= //' input.file> output.file 
     
     real 0m3.310s 
     user 0m3.212s 
     sys 0m0.092s 
    
  • Perl -pe 's/.*= //'-iオプションは、ここでの生産性に大きな違いをもたらさない)

     $ time Perl -i.bak -pe 's /.*= //' input.file 
     
     real 0m3.187s 
     user 0m3.128s 
     sys 0m0.056s 
    
     $ time Perl -pe 's /.*= //' input.file> output.file 
     
     real 0m3.138s 
     user 0m3.036s 
     sys 0m0.100s 
    
  • awk '{print $NF}'

     $ time awk '{print $ NF}' input.file> output.file 
     
     real 0m1.251s 
     user 0m1.164s 
     sys 0m0.084s 
    
  • cut -c 35-

     $ time cut -c 35- input.file> output.file 
     
     real 0m0.352s 
     user 0m0.284s 
     sys 0m0。 064s 
    
  • cut -d= -f2

     $ timecut -d = -f2input.file> output.file 
     
    実際の0m0.328s 
     user 0m0.260s 
     sys 0m0.064s

アイデアのソース。

13
pa4080

行プレフィックスは常に同じ長さ(34文字)であるため、cutを使用できます。

cut -c 35- < input.txt > output.txt
11
David Foerster

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

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

Perl-sパターン/.*= /を空の文字列に置き換える//

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の answer のアプローチよりも数倍速いため、このアプローチに言及します。

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...
    
4
pa4080