文字列の左側を削除する方法は?


144

私はいくつかの簡単なPythonコードの文字列などを検索ファイルその持ってpath=c:\pathc:\path一部は変更になる場合があります。現在のコードは次のとおりです。

def find_path(i_file):
    lines = open(i_file).readlines()
    for line in lines:
        if line.startswith("Path="):
            return # what to do here in order to get line content after "Path=" ?

後にテキストを取得する簡単な方法は何Path=ですか?


「Path =」で始まるファイル内の最初の行に戻ることに注意してください。この投稿への他の回答も行います。しかし、ファイルがDOSバッチファイルのようなものである場合、「バッチ」またはコマンドファイルが条件で満たされていなくても、実際にはそのようなファイルの最後の行を必要とする場合があります。
DevPlayer

回答:


22

以降Python 3.9、以下を使用できますremoveprefix

'Path=helloworld'.removeprefix('Path=')
# 'helloworld'

4
時間旅行はたくさん?;-) PEP 596から-Python
ssc

私はpython 3.9のソリューションを作成するつもりでしたが、どこでもpython 3.9ソリューションについて言及したようです。:)
Pygirl

196

文字列が固定されている場合は、次のように使用できます。

if line.startswith("Path="):
    return line[5:]

これにより、文字列の5番目以降のすべてが得られます(文字列もシーケンスなので、これらのシーケンス演算子もここで機能します)。

または、最初に行を分割することもできます=

if "=" in line:
    param, value = line.split("=",1)

次に、paramは "Path"で、valueは最初の=の後の残りです。


3
splitメソッドの+1は、len(prefix)での手動スライシングのわずかな醜さを回避します。
ボビンス2009年

1
しかし、入力がすべて「something = somethingelse」の形式でない場合にもスローされます。
Dan Olson、

1
そのため、条件を前に置いて、「=」が文字列にある場合にのみ使用されます。それ以外の場合は、split()の結果の長さ、および== 2かどうかをテストすることもできます。
MrTopf 2009年

7
Dan Olsonが言うsplitように、区切り文字が存在しない場合は例外をスローします。partitionより安定しています。また、文字列を分割し、常に、前、区切り、および後のコンテンツ(''区切り文字が存在しない場合もあります)を含む3要素のタプルを返します。例えば、value = line.partition('=')
Anders Johansson

1
区切り文字が存在しない場合、Splitは例外をスローせず、文字列全体のリストを返します。少なくともpython 2.7の下
マキシム

122

文字列から接頭辞を削除する

# ...
if line.startswith(prefix):
   return line[len(prefix):]

セパレータの最初の出現で分割 str.partition()

def findvar(filename, varname="Path", sep="=") :
    for line in open(filename):
        if line.startswith(varname + sep):
           head, sep_, tail = line.partition(sep) # instead of `str.split()`
           assert head == varname
           assert sep_ == sep
           return tail

ConfigParserを使用してINIのようなファイルを解析する

from ConfigParser import SafeConfigParser
config = SafeConfigParser()
config.read(filename) # requires section headers to be present

path = config.get(section, 'path', raw=1) # case-insensitive, no interpolation

別のオプション


1
4つのスペースではなく3つのスペースをインデントするまれな理由の1つ。
ボブスタイン

25
def remove_prefix(text, prefix):
    return text[len(prefix):] if text.startswith(prefix) else text

1
「else text」を「else False」または「else None」など、ファイル内の行が「Path =」で始まらなかったことを示すために返したい-type-に置き換えることができるので、これが好きです。個人的には、視覚的に目立つように、3項演算子を括弧で囲むのが好きです。
DevPlayer 2016

19

一般に、スライス(条件付きまたは非条件付き)については、同僚が最近提案したものを好みます。空の文字列で置き換えてください。コードが読みやすくなり、コードが(場合によっては)少なくなり、間違った文字数を指定するリスクが少なくなります。OK; 私はPythonを使用していませんが、他の言語ではこのアプローチを好みます。

rightmost = full_path.replace('Path=', '', 1)

または-この投稿への最初のコメントをフォローアップする-これを行うだけの場合 行が次始まる場合に場合Path

rightmost = re.compile('^Path=').sub('', full_path)

上記で提案されているものとの主な違いは、「マジックナンバー」(5)が含まれていないこと、および ' 5' 文字列 ' Path='の両方を指定する必要がないことです。つまり、コードメンテナンスからこのアプローチを好みます視点。


機能しません: 'c = Path = a'.replace( "Path ="、 ""、1)->' c = a '。
jfs 2009年

3
これは、「Path =」で始まる文字列の元の要件を満たしていません。
子犬

1
正規表現のコードを単にに置き換えることができrightmost = re.sub('^Path=', '', fullPath)ます。このcompile()メソッドの目的は、コンパイルされたオブジェクトを再利用する場合に処理を高速化することですが、使用後に破棄するため、ここでは何の効果もありません。とにかく、通常、この最適化について心配する価値はありません。
ジムオールドフィールド2016

13

popはインデックスを作成する方が好き[-1]です:

value = line.split("Path=", 1).pop()

value = line.split("Path=", 1)[1]
param, value = line.split("Path=", 1)

2
「マジックナンバー」なしの素晴らしい選択肢。これstartswithはすでにテストされているので機能することは注目に値しsplitます。split("Path=", 1)より正確です(プレフィックスが文字列の後半に現れる場合)が、マジックナンバーが再導入されます。
2013年

1
(非常に重要な)以前のコメントの短いバージョン:これは、最初にstartswith()でテストした場合にのみ機能します。
MarcH 2013年


5

どう?

>>> line = r'path=c:\path'
>>> line.partition('path=')
('', 'path=', 'c:\\path')

このトリプレットは、ヘッド、セパレーター、テールです。


これはすべての場合で同じように機能するわけではありません。セパレータが存在する場合、結果は3番目のアイテムになります。それ以外の場合、結果は最初のアイテムです。
Ioannis Filippidis 2017

5

私が考えることができる最も簡単な方法は、スライスすることです:

def find_path(i_file): 
    lines = open(i_file).readlines() 
    for line in lines: 
        if line.startswith("Path=") : 
            return line[5:]

スライス表記について簡単に説明します。通常のインデックスではなく2つのインデックスを使用します。最初のインデックスは、スライスに含めたいシーケンスの最初の要素を示し、最後のインデックスは、スライスに含めたい最後の要素の直後のインデックスです。
例えば:

sequence_obj[first_index:last_index]

スライスは、間のすべての要素で構成さfirst_indexlast_indexを含む、first_index及びませんlast_index。最初のインデックスを省略すると、デフォルトでシーケンスの先頭になります。最後のインデックスを省略すると、シーケンスの最後の要素までのすべての要素が含まれます。負のインデックスも使用できます。トピックの詳細については、Googleを使用してください。


4
>>> import re

>>> p = re.compile(r'path=(.*)', re.IGNORECASE)

>>> path = "path=c:\path"

>>> re.match(p, path).group(1)
'c:\\path'

1. r''Windowsパスには文字列を使用します。2. re.match()Noneを返す場合があります
jfs 2009年

3

ここで言及されていないもう1つのシンプルなワンライナー:

value = line.split("Path=", 1)[-1]

これは、さまざまなエッジケースでも適切に機能します。

>>> print("prefixfoobar".split("foo", 1)[-1])
"bar"

>>> print("foofoobar".split("foo", 1)[-1])
"foobar"

>>> print("foobar".split("foo", 1)[-1])
"bar"

>>> print("bar".split("foo", 1)[-1])
"bar"

>>> print("".split("foo", 1)[-1])
""



1

リスト内包表記を知っている場合:

lines = [line[5:] for line in file.readlines() if line[:5] == "Path="]

line.startswith(...)10倍高速であることを示唆する編集がありました。私のテストはこれを確認しませんでした。その主張を裏付ける証拠が提供されたら、喜んでそれを変更してください。
Matthew Schinckel 2014年

0

ポップバージョンは完全に正しくありませんでした。私はあなたが望むと思います:

>>> print('foofoobar'.split('foo', 1).pop())
foobar

0

エスケープで正規表現を使用しないのはなぜですか? ^行の最初の部分とre.MULTILINE一致し、各行で一致します。re.escape一致が正確であることを保証します。

>>> print(re.sub('^' + re.escape('path='), repl='', string='path=c:\path\nd:\path2', flags=re.MULTILINE))
c:\path
d:\path2

0

以下のコードを試してください

if line.startswith("Path="): return line[5:]

1
あなたの答えと受け入れられた答えの違いは何ですか?それは他の答えの最初の部分にあることがわかります。
eyllanesc

-1

これはまさにあなたが探しているものだと思います

    def findPath(i_file) :
        lines = open( i_file ).readlines()
        for line in lines :
            if line.startswith( "Path=" ):
                output_line=line[(line.find("Path=")+len("Path=")):]
                return output_line

-1

関数を記述する必要がない場合、これはリストに従って分割されます。この場合は 'Mr. | Dr. | Mrs。'で、[1]で分割後にすべてを選択し、再度分割して要素を取得します。以下の場合、「モリス」が返却されます。

re.split('Mr.|Dr.|Mrs.', 'Mr. Morgan Morris')[1].split()[1]

-1

これは他の答えと非常によく似ていますが、文字列操作が繰り返されず、接頭辞が存在したかどうかを判断する機能があり、非常に読みやすくなっています。

parts = the_string.split(prefix_to_remove, 1):
    if len(parts) == 2:
        #  do things with parts[1]
        pass
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.