我有一个文件,里面有很多像这样提到的GUID
Dlg1={929EC5C7-0A40-4BE4-8F0A-60C3CB4A62A7}-SdWelcome-0
我想用已经使用工具生成的新GUID的最后8位替换这些GUID的最后8位数,到目前为止我尝试过的是
读取生成的GUID的最后8位数字,如此
$GUID=~/[0-9a-fA-F]{8}/;
将其分配给新变量,如
$newGUID =$1;
现在尝试将其替换为文件
中的旧GUIDif ($line =~/^.* {(.*)}/) {
$line =~s/[0-9a-fA-F]{8}}/$newGUID/;
}
但它似乎没有工作,它用新的GUID的32位替换旧GUID的最后8位数,任何想法如何实现它。
答案 0 :(得分:4)
它将旧GUID的最后8位替换为32位新GUID,任何想法如何实现它。
你现在有了这个:
$line =~s/[0-9a-fA-F]{8}}/$newGUID/;
您说用全部32位新GUID替换GUID的最后八个字符。这意味着你的发现和替换正确的角色,但是你用它替换它是错误的。
$newGUID
等于什么?它是一个完整的32位GUID吗?如果是这样,你需要拉下最后8个字符。
我会推荐两件事。
[[:xdigit:]]
而不是[0-9a-fA-F]
。虽然两者都非常相同。使用:xdigit:
更清晰,更容易理解。在这种情况下,您应该使用substr而不是正则表达式。您确切地知道自己想要什么,并且知道字符串中的位置。 substr
命令可以让您更容易理解,更清晰:
use constant {
GUID_RE => qr/^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}$/,
};
my $old_guid = '929EC5C7-0A40-4BE4-8F0A-60C3CB4A62A7';
my $new_guid = 'oooooooo-oooo-oooo-oooo-ooooXXXXXXXX';
# Regular expressions are great for verifying formats!
if ( not $old_guid =~ GUID_RE ) {
die qq(Old GUID "$new_guid" is not a GUID string);
}
if ( not $new_guid =~ GUID_RE ) { # Yes, I know this will die in this case
die qq(New GUID "$new_guid" is not a GUID string);
}
# Easy to understand, I'm removing the last eight characters of $old_guid
# and appending the last eight digits of $new_guid
my $munged_guid = substr( $old_guid, 0, -8 ) . substr( $new_guid, -8 );
say $munged_guid; # Prints 929EC5C7-0A40-4BE4-8F0A-60C3XXXXXXX
我正在使用正则表达式来验证GUID格式是否正确,这对于正则表达式来说是一项很棒的任务。
我定义了一个GUID_RE常量。你可以查看它是如何定义的,并验证它是否是正确的格式(12个十六进制数字,4个十六进制数字,4个十六进制数字和12个十六进制数字全部用破折号分隔)。
然后,我可以在我的程序中使用GUID_RE
常量,并且很容易看出我在做什么。我的GUID实际上是GUID_ID格式吗?
使用substr
代替正则表达式可以轻松查看我正在做的事情。我将$old_guid
中的最后八个字符移除,并附加$new_guid
的最后八个字符。
同样,您的直接问题是您的s/.../.../
找到了正确的字符,但您的替换字符串不正确。但是,这不是正则表达式的最佳用法。
答案 1 :(得分:3)
我认为你的问题是你没有正确地将$1
设置为最后8位数(如果它来自该正则表达式,它将匹配前8位数并且不设置任何组)。你可以尝试$newGUID = substr($GUID, -8);
之类的东西。我还认为$ GUIDTail之类的东西对变量更有意义,因为它不存储整个guid。
此外,目前你正在吃闭合的大括号。您应该在newGuid / guidTail中包含它,将其包含在s///
调用中,或者将匹配中的卷曲更改为(?=\})
(表示匹配此但不包括在匹配中)。
P.S。你假设那里只有一个guid就行了。如果有多个guid的可能性(或以其他方式消除你想要修改的那个,那么你可能想要为匹配添加一个全局修饰符,但这只会替换第一个)。
答案 2 :(得分:2)
这是一个小代码片段,演示了我认为你所遵循的原则。首先,我从一个给定的字符串开始,然后取出它的最后8个字符并将其存储在一个新变量$insert
中。然后我对输入数据执行一些严格的替换(这里是内部文件句柄DATA
,这在演示时很方便),并打印更改后的字符串。
替换中的正则表达式查找大括号{ ... }
,其中包含十六进制数字[:xdigit:]
和短划线\-
([[:xdigit:]\-]+
),后跟八位十六进制数字。 \K
转义允许我们在其之前“保留”匹配的字符串,因此我们需要做的就是插入我们存储的字符串,并替换结束的大括号。
如果您希望在文件上尝试此操作,请将<DATA>
更改为<>
并按以下方式运行:
perl script.pl input
<强>代码:强>
use strict;
use warnings;
my $new = "929EC5C7-0A40-4BE4-8F0A-1234567890";
my $insert = substr($new, -8);
while (<DATA>) {
s/\{[[:xdigit:]\-]+\K[[:xdigit:]]{8}\}/$insert}/i;
print;
}
__DATA__
Dlg1={929EC5C7-0A40-4BE4-8F0A-60C3CB4A62A7}-SdWelcome-0
<强>输出:强>
Dlg1={929EC5C7-0A40-4BE4-8F0A-60C334567890}-SdWelcome-0