次のような正規表現がありますが、変数$ regexにファイルから読み込んだので、デザイン時にその内容がわかりませんが、実行時には私はそれが "バージョン1"、 "バージョン2"、 "バージョン3" と "バージョン4" という名前のグループ含まれていることを発見することができます。Powershell:正規表現の名前付きグループを変数に置き換える
"Version (?<version1>\d),(?<version2>\d),(?<version3>\d),(?<version4>\d)"
を...と私は、これらの変数を持っている:
$version1 = "3"
$version2 = "2"
$version3 = "1"
$version4 = "0"
を..私はファイル内の次の文字列に遭遇します:
Version 7,7,0,0
...($ input -match $ regex)が$ trueと評価されるように、変数$ inputに格納されています。
文字列$ inputの$ regexの名前付きグループを、$ regex($ 1、$ 2、$ version3、$ version4)の値で置き換えることはできますか? $ regexにはこれらの名前付きグループが含まれていることだけを知っていますか?)
グループ名を一致のインデックスとして使用して、名前付きグループを変数の値に置き換える構文についての説明はありません。これはこれでもサポートされていますか?
EDIT: を明確にする - 目標は、指定したファイル内のバージョン文字列は、バージョンフィールドの可変数の交換が必要なテキストファイルの任意の種類でテンプレートのバージョン文字列を置き換えることである(2、3可能性があり、または4つすべてのフィールド)。たとえば、ファイル内のテキストは、これらのいずれかのように見えることができます(ただし、これらに限定されない):で
#define SOME_MACRO(4, 1, 0, 0)
Version "1.2.3.4"
SomeStruct vs = { 99,99,99,99 }
ユーザーは、ファイルセットとフィールドを含む行にマッチする正規表現を指定することができます元のアイデアは、個々のフィールドが名前付きグループによってキャプチャされるということです。ユーティリティには、ファイル内で置換する必要がある個々のバージョンフィールド値がありますが、置換を含む行の元の形式を保持し、要求されたフィールドのみを置換する必要があります。
EDIT-2: は私が、私は試合のそれぞれの位置や程度に基づいて、サブストリングの計算に必要な結果を得ることができると思うが、PowerShellのの置換操作は、私にいくつかの作業を保存するつもりだった期待していました。
EDIT-3:正しくかつ簡潔に以下の記述Ansgarのよう ので、そこだけ元の入力文字列、あなただけの名前のグループを知っているかについて、正規表現を使用した方法は(ではない、そして得られました"-replace"演算(または他の正規表現演算)を使用して、指定されたグループのキャプチャの置換を実行し、残りの残りの文字列はそのまま残します。この問題のために、誰かが好奇心が強い場合は、以下の解決策を使用して終了しました。 YMMV、他の解決策が可能です。彼のフィードバックとオプションを提供してくれたAnsgarに感謝します。次のコードブロック内
:
- $入力が行われる
- $正規表現は、(タイプの[文字列])正規表現である置換にテキストの行では、ファイルから読み込まサポートされている名前付きグループの少なくとも1つを含むことが検証されている
- $ regexToGroupNameは、正規表現文字列を、[regex] :: GetGroupNamesによって返される配列の順序に従ってグループ名の配列にマッピングするハッシュテーブルです()は、式に表示される左から右の順番に一致します
- $ groupNameToVersionNumberは、グループ名をバージョン番号にマップするハッシュテーブルです。
$ regex内の名前付きグループの制約は、名前付きグループ内の式をネストすることができず、入力文字列内で最大で1回一致する必要があります(私は思う)。
# This will give us the index and extent of each substring
# that we will be replacing (the parts that we will not keep)
$matchResults = ([regex]$regex).match($input)
# This will hold substrings from $input that were not captured
# by any of the supported named groups, as well as the replacement
# version strings, properly ordered, but will omit substrings captured
# by the named groups
$lineParts = @()
$startingIndex = 0
foreach ($groupName in $regexToGroupName.$regex)
{
# Excise the substring leading up to the match for this group...
$lineParts = $lineParts + $input.Substring($startingIndex, $matchResults.groups[$groupName].Index - $startingIndex)
# Instead of the matched substring, we'll use the substitution
$lineParts = $lineParts + $groupNameToVersionNumber.$groupName
# Set the starting index of the next substring that we will keep...
$startingIndex = $matchResults.groups[$groupName].Index + $matchResults.groups[$groupName].Length
}
# Keep the end of the original string (if there's anything left)
$lineParts = $lineParts + $input.Substring($startingIndex, $input.Length - $startingIndex)
$newLine = ""
foreach ($part in $lineParts)
{
$newLine = $newLine + $part
}
$input= $newLine
これはいいと思いますが、これはユーザが正規表現とファイルセットを指定するユーティリティのためです。正規表現はわかりませんし、ファイルの内容がわからないので、元のファイルの内容を再フォーマットせずに最初の行を使用することはできません。これは望ましくありません。後で同じように見えるファイルの内容を残して、一致する行の部分文字列だけを個別のバージョンフィールドに置き換えなければなりません。 – Hoobajoob
おそらく、正規表現の名前付きグループを実際の古い/新しい番号で置き換えて、文字列置換を行うことができます。ただし、正規表現に名前付きグループ以外の式が含まれていると正しく動作しません。 –
正規表現内の名前付きグループがどのように実際に定義されているかを事前に知ることはできませんが(例えば、\ d、\ d {2}、\ d +、リテラルなどを探すことができます) 。私は、名前付きグループの定義にいくつかの制約を導入し、上記のforループで使用される正規表現を、正規表現の構文と英数字から1つ以上の文字を許可するように変更することができます(例えば、正規表現内の "\\ d" forループは "[a-zA-Z0-9 \\ + \。\ * \?\ \ \ \ \ \ \ \ \ \] \")。いずれにせよ、この方法は部分文字列操作よりも好ましい方法です。 – Hoobajoob