Excel:文字列内の最後の文字/文字列の一致


187

基本関数を使用して文字列内の最後の文字/文字列の一致を識別する効率的な方法はありますか?すなわちない最後の文字/文字列文字列が、文字/文字列の最後に出現する位置にある文字列。 Searchそして、find仕事の両方が左から右に私は長い再帰アルゴリズムずに適用する方法を考えることができないようにします。そして、この解決策はもはや時代遅れのようです。


3
例えばピリオド "。"の最後のインスタンスの位置が欲しいからです。文字列 "one.two.three.four"内
geotheory

6
質問の誤った読み方が賛成票を集めるのをおもしろくする
ジオセオリー2013

1
別の観点から見てみると、他の人もあなたの質問の意味が理解できなかったため、提案が正しい解決策であると考えました。選択した回答でさえ「意味を理解する」...批判ではなく、人々がより簡単に答えられるように、質問をより理解しやすくすることを目指す要求です。
John Bustos 2013

私は質問に例を追加しましたはずですが、私は、文字列の最後の文字の問い合わせからこれを区別するために十分だったと思う:searchfindの両方のクエリ文字列の内容は、「試合では」標準語、プラスリンクされている例です。
地質学2013

回答:


1

excelの新しいバージョンでは、新しい関数、つまり新しいメソッドが登場します。以前のバージョンでは複製可能ですが(まだ見たことはありません)、Excel O365を使用すると、次のように使用できます。

=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),1)="Y"))

これは、(重複する)サブストリングの最後の位置を取得するためにも使用できます。

=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),2)="YY"))

| Value  | Pattern | Formula                                        | Position |
|--------|---------|------------------------------------------------|----------|
| XYYZ   | Y       | =MATCH(2,1/(MID(A2,SEQUENCE(LEN(A2)),1)="Y"))  | 3        |
| XYYYZ  | YY      | =MATCH(2,1/(MID(A3,SEQUENCE(LEN(A3)),2)="YY")) | 3        |
| XYYYYZ | YY      | =MATCH(2,1/(MID(A4,SEQUENCE(LEN(A4)),2)="YY")) | 4        |

これにより、任意の置換文字を使用できなくなり、パターンの重複が可能になりますが、「欠点」は配列の使用です。


注:古いバージョンのExcelでも同じ動作を強制できます。

=MATCH(2,1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"))

から入力するCtrlShiftEnterか、インラインINDEXを使用して暗黙的な交差を取り除きます。

=MATCH(2,INDEX(1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"),))

1
完全な歴史的名誉は@ tigeravatarの長年のソリューションに属しているのに、私は、今、この継承ダニを考えるstackoverflow.com/a/18617720/1156245
geotheory

注:私の提案は大雑把なコードゴルフで勝つでしょうが、大量に使用する場合、配列の使用は必ずしも推奨されません。しかし、それは私が明示的に言及しようとした他の利点があります。これにより、@ Tigeravatarによる回答が以前と同様に適切になります。
JvdV

345

私はあなたが何を意味するか理解していると思います。たとえば、次の文字列(セルA1に格納されている)の右端の\が必要だとします。

ドライブ:\ Folder \ SubFolder \ Filename.ext

最後の\の位置を取得するには、次の式を使用します。

=FIND("@",SUBSTITUTE(A1,"\","@",(LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))/LEN("\")))

これは、右端の\が文字24にあることを示しています。これは、「@」を探し、最後の「\」を「@」に置き換えることによって行われます。それを使用して最後のものを決定します

(len(string)-len(substitute(string, substring, "")))\len(substring)

このシナリオでは、部分文字列は単純に "\"で、長さは1であるため、最後に除算を省略して次のように使用できます。

=FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))

これを使用して、フォルダーパスを取得できます。

=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))))

末尾に\がないフォルダパスは次のとおりです

=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))-1)

そして、ファイル名だけを取得するには:

=MID(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))+1,LEN(A1))

ただし、これは特定のキャラクターの最後のインスタンスの右側にすべてを取得する代替バージョンです。したがって、同じ例を使用すると、ファイル名も返されます。

=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))

24
頭が回転する; 頭の回転; 頭が回転する; 「わかった-理解せずにこれを使いたくないので、ええと、ええと、ええと、ええと...何を待っているのですか?うわぁ!本当に?それは天才です!私は数時間でそのことを考えていなかったと確信しています数日でも数週間でもない!」-+1、悲しいことに、自分で+5または+10を行うのは難しいので---もしあなたが行き詰まっている場合の説明:(例を使用)SUBSTITUTEすべての(3)のインスタンスに\何もない(文字列の長さを短くする)3)->それ\(3番目)は最後のものです。それをユニークなものに置き換えてFIND、そのユニークなキャラクターの位置...素晴らしい...ありがとう!
コードジョッキー

7
賢いです。セルにまだ「@」が含まれていないことに注意する必要があります。それ以外の場合は、何か他のものをサブスクライブする必要があります。@ gwin003で提案されているように=ISNUMBER(SEARCH("@",A1))使用して確認できます。
ジオセオリー2014

3
最後のオカレンスの右側にあるすべてを抽出する最後のオプションは、私が「文字列y内の文字列xの最後のオカレンス」を探していたので、たいへんありがたく思っています。その最後の発生の権利。
SSilk

1
なんで99?これらのさまざまな文字列の長さが99未満であると想定していますか?そのような仮定をしないこの答えこの答えを見てください。
ジャン=フランソワ・コルベット

2
「@」の代わりに、CHAR(9)(タブ文字)を使用しました。これは、元々データがタブ区切りファイルから取得されたものであり、データに含まれないことが保証されているためです。
Josiah Yoder

28

カスタム関数を作成し、それを数式で使用してみませんか?VBAには組み込み関数がありInStrRevます。これは、まさにあなたが探しているものを実行します。

これを新しいモジュールに入れます:

Function RSearch(str As String, find As String)
    RSearch = InStrRev(str, find)
End Function

そして、関数は次のようになります(元の文字列がB1にあると想定)。

=LEFT(B1,RSearch(B1,"\"))

2
これは非常に単純化されていますが、有効なソリューションです。プロジェクトでVBAを使用できる場合は、これを使用してください。
Patrick Hofman

7

tigeravatarとJean-FrançoisCorbettは、この式を使用して、最後の「\」文字の右側に文字列を生成することを提案しました

=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))

セパレータとして使用される文字がスペース「」の場合、式を次のように変更する必要があります。

=SUBSTITUTE(RIGHT(SUBSTITUTE(A1," ",REPT("{",LEN(A1))),LEN(A1)),"{","")

言うまでもなく、「{」文字は、処理するテキストで「通常」は発生しない任意の文字に置き換えることができます。


この解決方法の方がエレガントで理解しやすいと思います。また、LEN(A1)に数値を掛けると、元の文字列にスペースが含まれていなければ、n番目から最後までの数を得ることができます(私にとってはそうでした)
Zlatin Zlatev

4

このソリューションを思いついただけで、VBAは必要ありません。

私の例で最後に出現する「_」を見つけます。

=IFERROR(FIND(CHAR(1);SUBSTITUTE(A1;"_";CHAR(1);LEN(A1)-LEN(SUBSTITUTE(A1;"_";"")));0)

裏返しに説明しました。

SUBSTITUTE(A1;"_";"") => replace "_" by spaces
LEN( *above* ) => count the chars
LEN(A1)- *above*  => indicates amount of chars replaced (= occurrences of "_")
SUBSTITUTE(A1;"_";CHAR(1); *above* ) => replace the Nth occurence of "_" by CHAR(1) (Nth = amount of chars replaced = the last one)
FIND(CHAR(1); *above* ) => Find the CHAR(1), being the last (replaced) occurance of "_" in our case
IFERROR( *above* ;"0") => in case no chars were found, return "0"

これがお役に立てば幸いです。


3

私が作成したこの関数を使用して、文字列内の文字列の最後のインスタンスを見つけることができます。

確かに、受け入れられたExcelの数式は機能しますが、読んで使用するのは非常に困難です。ある時点で、維持できるように小さなチャンクに分割する必要があります。以下の私の関数は読みやすいですが、名前付きパラメーターを使用して式で呼び出すため、それは無関係です。これにより、使用が簡単になります。

Public Function FindLastCharOccurence(fromText As String, searchChar As String) As Integer
Dim lastOccur As Integer
lastOccur = -1
Dim i As Integer
i = 0
For i = Len(fromText) To 1 Step -1
    If Mid(fromText, i, 1) = searchChar Then
        lastOccur = i
        Exit For
    End If
Next i

FindLastCharOccurence = lastOccur
End Function

私はそれを次のように使用します:

=RIGHT(A2, LEN(A2) - FindLastCharOccurence(A2, "\"))

2

@SSilk によって作成されたコメントの一部を考えると、私の最終目標は、最後の発生のすべてを正しく処理することでした。非常に単純な式を使用した代替アプローチは、A文字列の列(たとえば)をコピーし、そのコピー(たとえばColumnB)検索と置換を適用します。たとえば、例を挙げます:Drive:\Folder\SubFolder\Filename.ext

何を見つける

これFilename.extは、選択された文字の最後のインスタンス(ここ)の後に残っているもの(ここ)を返します\

=FIND(B1,A1)-1

1

私はパーティーに少し遅れますが、多分これは役立つかもしれません。質問のリンクにも同様の式がありましたが、私はエラーを取り除くためにIF()ステートメントを使用しています。

Ctrl + Shift + Enterを恐れていない場合は、配列数式を使用するとかなりうまくいくでしょう。

文字列(セルA1内): "one.two.three.four"

式:

{=MAX(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)))}  use Ctrl+Shift+Enter

結果:14

最初、

ROW($1:$99)

1から99までの整数の配列を返します{1,2,3,4,...,98,99}

次、

MID(A1,ROW($1:$99),1)

ターゲット文字列で見つかった長さ1の文字列の配列を返し、ターゲット文字列の長さに達した後、空の文字列を返します。 {"o","n","e",".",..."u","r","","",""...}

次、

IF(MID(I16,ROW($1:$99),1)=".",ROW($1:$99))

配列内の各アイテムを文字列「。」と比較します。文字列内の文字のインデックスまたはFALSEを返します。{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

最終、

=MAX(IF(MID(I16,ROW($1:$99),1)=".",ROW($1:$99)))

配列の最大値を返します: 14

この式の利点は、短く、比較的理解しやすく、固有の文字を必要としないことです。

短所は、Ctrl + Shift + Enterを使用する必要があることと、文字列の長さが制限されることです。これは以下に示すバリエーションで回避できますが、そのバリエーションは揮発性(読み取り:遅い)関数であるOFFSET()関数を使用します。

この式の速度が他の速度と比較してわかりません。

バリエーション:

=MAX((MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1)=".")*ROW(OFFSET($A$1,,,LEN(A1)))) works the same way, but you don't have to worry about the length of the string

=SMALL(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)),2) determines the 2nd occurrence of the match

=LARGE(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)),2) determines the 2nd-to-last occurrence of the match

=MAX(IF(MID(I16,ROW($1:$99),2)=".t",ROW($1:$99))) matches a 2-character string **Make sure you change the last argument of the MID() function to the number of characters in the string you wish to match!


0

VBAでこれを行う簡単な方法は次のとおりです。

YourText = "c:\excel\text.txt"
xString = Mid(YourText, 2 + Len(YourText) - InStr(StrReverse(YourText), "\" ))

0

パーティーにはかなり遅れましたが、簡単な解決策はVBAを使用してカスタム関数を作成することです。

WorkBook、Worksheet、またはVBAモジュールのVBAに関数を追加する

Function LastSegment(S, C)
    LastSegment = Right(S, Len(S) - InStrRev(S, C))
End Function

次に、セルの数式

=lastsegment(B1,"/")

セル内で、セルB1で検索される文字列は、セルB1の最後の「/」の後に続くテキストをセルに入力します。長さの制限、あいまいな式はありません。私が考えることができる唯一の欠点は、マクロが有効なワークブックの必要性です。

この方法でユーザーVBA関数を呼び出し、セルの数式に値を返すことができます。組み込みのExcel関数のパラメーターとしても使用できます。

関数を頻繁に使用する場合は、文字が文字列にない場合、文字列が空白であるなどのケースを確認する必要があります。


0

細胞 A1 = find/the/position/of/the last slash

簡単な方法は、テキストを逆にして、最初のスラッシュを通常どおりに見つけることです。これで、テキスト全体からこの数値を引いた長さが得られます。

そのようです:

=LEN(A1)-FIND("/",REVERSETEXT(A1),1)+1

これは最後の/の位置である21を返します


REVERSETEXTは標準のExcel式ではありません
d219
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.