0

Python の文字列操作について助けが必要です (以前の長い質問を以下のこの問題に要約しました)。

ファイルからのこの行の場合:

L20B, CVS=1, HTYP=16, MLV=25

2 番目のフィールドは、CVS または VS です。関連データは行末まで存在します。

CVS または VS で始まる部分を別の文字列に置き換える必要があります。

if CVS found, then replacement is CFIXD(0,1,0) -OR-
if VS found, then replacement is FIXD(0,1,0)

例:

old line: L20B, CVS=1, HTYP=16, MLV=25
new line: L20B, CFIXD(0,1,0)

Old line: T10, M312, P10, Z3710, CL=L1, RH=1  (here, identify RH only and replace with)
New line: T10, M312, P10, Z3710, CL=L1, FIXD(0,1,0)

Old line: T20, M312, P20, Z100, CKR=10000 DV(0,1,0) 
New line: T20, M312, P20, Z100, CLS(0,1,0), MU=0.35

So, the replacement string keeps changing with what is found.
CVS or VS (till end of line) is replaced with CFIXD(0,1,0) or FIXD(0,1,0)
CRH or RH (till end of line) is replaced with CVR(0,1,0) or VR(0,1,0)
CFIXD or FIXD (till end of line) is replaced with CVR(0,1,0) or VR(0,1,0)
20 other variants.

Also, is it possible to modify the re.sub() expression to identify something in the search string and carry it over to the replacement string?
For e.g., 
Search for CFIXD(x,y,z) - replace with CVR (x,y,z) 

CVS(またはVS)の後のデータは、

CVS=2, HTYP=11, MLV=25 
VS=4, HTYP=9, MLV=5      etc. 

ご覧のとおり、長さも異なる場合があります。私が確かに知っている唯一のことは、CVS または VS で始まる文字列がその行の終わりまで続くということです。私の知る限り、上記の長さとデータが異なるため、 string.replace は機能しません。

すぐに利用できる Python メソッドはありますか? または、これを行うには小さなルーチンを作成する必要がありますか? VS または CVS へのインデックス (string.find を使用) を見つけて、そのポイントから行末までのすべてを置き換えることができます。簡単な(私には向いていない)正規表現の方法があることは知っています。ありがとう。

4

2 に答える 2

3

正規表現を使用します。

import re
re.sub(r'(C|)VS=.*', r'\1FIXD(0,1,0)', line)

説明:

# regex
  (C|)         # optionally match a 'C', save it or an empty string in group 1
  VS=          # match 'VS='
  .*           # match to the end of the line

# replacement
  \1           # the contents of group 1 (either 'C' or an empty string)
  FIXD(0,1,0)  # the literal string 'FIXD(0,1,0)'

例:

>>> re.sub(r'(C|)VS=.*', r'\1FIXD(0,1,0)', 'L20B, CVS=1, HTYP=16, MLV=25')
'L20B, CFIXD(0,1,0)'
>>> re.sub(r'(C|)VS=.*', r'\1FIXD(0,1,0)', 'L20C, VS=4, HTYP=9, MLV=5')
'L20C, FIXD(0,1,0)'

編集:ここでの編集に基づいて、さまざまなケースのいくつかの選択肢があります。

  • CVSまたはVS->CFIXD(0,1,0)またはFIXD(0,1,0)

    re.sub(r'(C|)VS=.*', r'\1FIXD(0,1,0)', line)
    
  • CRHまたはRH->CVR(0,1,0)またはVR(0,1,0)

    re.sub(r'(C|)RH=.*', r'\1VR(0,1,0)', line)
    
  • CFIXD(x、y、z)またはVIXD(x、y、z)-> CVR(x、y、z)またはVR(x、y、z)

    re.sub(r'(C|)FIXD(\([^)]*\)).*', r'\1VR\2', line)
    

の説明(\([^)]\)).*

(         # start second capture group
   \(       # match a literal '('
   [^)]*    # match any number of characters that are not ')'
   \)       # match a literal ')'
)         # end capture group
.*        # match to the end of the line
于 2012-12-13T19:53:32.587 に答える
1

正規表現を使用できますが、文字列をリストに分割する方が簡単です。

line = "L20B, CVS=1, HTYP=16, MLV=25"

line = line.split(", ")
if line[1].startswith("CVS="):
    line[1:] = ["CFIXD(0,1,0)"]
elif line[1].startswith("VS="):
    line[1:] = ["FIXD(0,1,0)"]

line = ", ".join(line)

これらの 2 つのケースはかなり似ているため、いくつかのジガリー ポケリーと組み合わせることができますが、この方法では完全に読みやすいように見えます。

于 2012-12-13T20:03:21.063 に答える