3

Tclの文字列から部分文字列を抽出しようとしています。私はコードを書いてそれを行うことができましたが、他に効率的な方法があるかどうか疑問に思いました。だから正確な問題は私が文字列を持っていることです

name_ext_10a.string_10a.string.string.string

「」を抽出し、その「」name_extを削除して「_」に置き換え.ます。最終的に出力を「name.ext」にします。私はこのようなものを書きました:

set _File "[string replace $_File [string last "_" $_File] [string length $_File] "" ]"
set _File "[string replace $_File [string last "_" $_File] [string length $_File] "" ]"
set _File "[string replace $_File [string last "_" $_File] [string last "_" $_File] "." ]"

これで私が望む正確な出力が得られますが、Tclでこれを行う他の効率的な方法があるかどうか疑問に思いました。

4

2 に答える 2

5

アンダースコアを区切り文字として使用してそのファイル名を分割し、最初の2つの要素をドットで結合することができます。

% set f name_ext_10a.string_10a.string.string.string
name_ext_10a.string_10a.string.string.string
% set out [join [lrange [split $f _] 0 1] .]
name.ext

編集

したがって、「名前」に任意の数のアンダースコアを含めることができる場合は、次のようになります。

set f "foo_bar_baz_ext_10a.string_10a.string.string.string"
set pieces [split $f _]
set name [join [lrange $pieces 0 end-3] _]
set out [join [list $name [lindex $pieces end-2]] .]  ;#==> foo_bar_baz.ext

しかし、これは複雑になっています。1つの正規表現で十分です。「文字列」はアンダースコア以外の文字の任意のシーケンスであると思います。

set string {[^_]+}
set regex "^(.+)_($string)_10a.${string}_10a.$string.$string.$string\$"
regexp $regex $f -> name ext
set out "$name.$ext"    ;#==> foo_bar_baz.ext
于 2012-08-29T01:47:08.877 に答える
2

抽出を行う 1 つの方法は、次のregsubとおりです。

regsub {^([^_]+)_([^_]+)_.*} $_File {\1.\2} _File

正規表現には、アンダースコア以外の文字のシーケンスに一致するコンポーネントと、アンカーといくつかのアンダースコア、および他のすべてに一致([^_]+)する末尾の非キャプチャが含まれています (したがって、破棄できます)。.*これregsub(文字列全体) を、一致する 2 つのアンダースコア以外のセクションを between で連結したものに置き換え、それを文字列の元の変数に.書き戻します。_File

正規表現と置換を中かっこで囲んでいることに注意してください。regsubこれは、Tcl に逐語的に渡したい Tcl メタ文字 (角括弧とバックスラッシュ) が含まれているためです。

于 2012-08-29T05:32:55.250 に答える