行の内容に基づいてファイル内の特定の行を置き換える方法[閉じる]

行の内容に基づいてファイル内の特定の行を置き換える方法[閉じる]

次のファイルがあります(例:

first line sss case-2-hello-world other words
second line other words
third line sss case-1-love-you other words
fourth line other words
fifth line other words
sixth line sss case-6-not-work other words

私はそれを次のように変換したいと思います:

pp:12 pme:4 plan:cpu_bind=hello mem_bind=world 
second line other words 
pp:6 pme:2 plan:cpu_bind=love mem_bind=you
fourth line other words 
fifth line other words 
pp:36 pme:12 plan:cpu_bind=not mem_bind=work 

まず、パターンのある線を識別しますsss。第二に、数字を抽出します。第三に、ppとpmeを計算しますpp=number*6 and pme=number*2。第四に、数字を含む行の単語を分割してcpu_bindsumsに割り当てますmem_bind。第五に、一緒に集めてラインを交換します。

たとえば、私は行を識別します

first line sss case-2-hello-world other words

sss数字は2です。その後は計算をする必要がありますpp=2*6 pme=2*2。文字列をcase-2-hello-world複数の部分に分割し、合計helloに割り当てますcpu_bind。最後に、私は得なければならないworldmem_bind

 pp:12 pme:4 plan:cpu_bind=hello mem_bind=world

元の行を交換してください。

注:sss行のどこにでも表示できますが、一度だけ表示されます。sss置き換える必要がある行を識別するために使用できる唯一のパターン。行には、数字と異なる数字を含む別の単語があります。パターンはcase-number-cpu_bind-mem_bind4つの部分で構成されています。その順序は決まっていて吐き出すことができる-

答え1

Python(2.x)では:

import sys

pat = 'sss'

for line in open(sys.argv[1]):
    if not pat in line:
        print line,
        continue
    case_nr = line.split(pat + ' case-', 1)[1].split('-')[0]
    print '**something about case{}**'.format(case_nr)

呼ぶpython script_name.py input.txt > output.txt

答え2

使用に問題がない場合sed

sed 's/\(.*\)sss case-\([0-9]*\)-.*/something about case\2/' input.txt 

答え3

これは複雑すぎるため、これを行うには完全なプログラミング言語を使用します。たとえば、Perlでは次のようになります。

$ perl -ne 'if(/\ssss\s+/ && /(\S+-\d+-\S+)/){
               @F=split(/-/,$1); 
               print "pp:",
                6 * $F[1],
                " pme:",2*$F[1],
                " plan:cpu_bind=$F[2] mem_bind=$F[3]\n"
             }else{print}' file 

または少しゴルフをするが、同じアイデアに従ってください。

$ perl -lpe '/\ssss\s+/&&do{/(\S+-\d+-\S+)/;@F=split(/-/,$1);
  $_="pp:".6*$F[1]." pme:".2*$F[1]." plan:cpu_bind=$F[2] mem_bind=$F[3]"}' file 

これは不正確な可能性があると仮定していることに注意してください(ただし、あなたの質問ではわかりません)。

  1. それに続く単語がsssあなたが興味のある単語であるとします。
  2. これは、単語が常に-サブ単語に分割されると仮定する。
  3. 単語には常に4つの部分があるとします。case最初の部分は数字で、2番目の部分は数字で、合計cpu_bindに割り当てる必要がある2つの単語がありますmem_bind

これらの仮定が正しいと仮定すると、これはスクリプトにコメントを追加するのと同じです。

#!/usr/bin/env perl

## Read the input file line by line
while (<>) {
    ## If this line matches whitespace (\s), then "sss", then one
    ## or more whitespace character, identify the string of interest
    ## by looking for non-whitespace characters (\S+), "-", then 
    ## numbers (\d+), then "-" and more non-whitespace characters and 
    ## save them as $1.
    if(/\ssss\s+/ && /(\S+-\d+-\S+)/){
        ## Split the word captured above into the @F array
        ## by cutting it on "-"
        @F=split(/-/,$1); 
        ## Start printing.
        print "pp:",
            ## 6 * the 2nd element in the array (the number)
            6 * $F[1],
                " pme:",2*$F[1],
                    ## The third element ($F[2]) is the 1st word
                    ## and the fourth element ($F[3]) is the 2nd word.
                    " plan:cpu_bind=$F[2] mem_bind=$F[3]\n"
                }
    ## If this line does not match "sss", print it.
    else{print}
}

答え4

私が理解したように説明すると、次のようになります。

 sed "/sss/{s/case1.*$/$case1;s/case2.*/$case2;s/case3.*/$case3}"

ただし、行全体を置き換える必要がある場合、または逆に単語を最後に保持する必要がある場合は、コメントでお問い合わせください。簡単に提供されます。

関連情報