我有以下情况,我需要从以username=xxx;
和password=yyy;
用户名和密码没有限制,但;
应该是每个关键字的分隔符,用户名后面总是username=
,密码后面跟着password=
。
我尝试构建以下内容,但我设法只得到部分想要的结果
set value "colour=blue;
age=25;
name=anthony;
username=firstuser;
username=hisuser;
password=test123"
set value2 "colour=blue;
age=25;
name=brothersofanthony;
username=seconduser;
password=test123;"
set value3 "username=user-3"
set value4 "username=user4"
regexp -nocase -- {\y(?:username=|password=)[a-z0-9]+} $value match match2
puts "value is $match and match2 is $match2"
regexp -nocase -- {\y(?:username=|password=)[a-z0-9]+} $value2 match match2
puts "value 2 is $match and match2 is $match2"
regexp -nocase -- {\y(?:username=|password=)[a-z0-9]+} $value3 match match2
puts "value 3 is $match and match2 is $match2"
regexp -nocase -- {\y(?:username=|password=)[a-z0-9]+} $value4 match match2
puts "value 4 is $match and match2 is $match2"
我正在尝试构建一个可以返回用户名和密码的正则表达式。使用上面的正则表达式,我设法只获得"用户名"如果用户名为[a-z0-9]
,则结果正确,而实际上它也可以是不同的符号(除了;
,因为它是分隔符)
如果找到多次出现在字符串中(例如value
,则有两个用户名,则应考虑第一个用户名)
上述正则表达式的第二个问题是它没有显示"密码"值,它需要与用户名具有相同的条件。
如何改进上述正则表达式?
答案 0 :(得分:1)
您需要在此特定情况下分隔匹配项,否则您将无法区分username
或password
。我建议使用一个正则表达式作为用户名,另一个用于密码。接下来,更改正则表达式,使字符类为[^;]+
而不是[a-z0-9]+
,以匹配除;
之外的所有字符。
set value "colour=blue;
age=25;
name=anthony;
username=firstuser;
username=hisuser;
password=test123"
regexp -nocase -- {\yusername=([^;]+)} $value - username
regexp -nocase -- {\ypassword=([^;]+)} $value - password
puts $username
puts $password
# => firstuser
# => test123
答案 1 :(得分:0)
像往常一样,正则表达式实际上远远超过必要的工作量。
proc getUsernameAndPassword record {
set res [dict create]
foreach {keyword value} [split [string map [list \n {}] $record] \;=] {
if {$keyword in {username password} && $keyword ni [dict keys $res]} {
dict set res $keyword $value
}
}
if {[dict size $res]} {
return $res
} else {
return None
}
}
如果在记录中找不到用户名或密码,则此命令将返回字符串None
。如果在记录中找到任一值,该命令将返回包含相关关键字(username
或password
)的列表,后跟值。如果找到这两个值,则列表将包含两个关键字,每个关键字后跟值。
该命令通过删除所有换行符,然后在每个分号或等号处拆分字符串,将您的记录转换为键值列表。如果关键字尚未添加到username
,则会检查每个键 - 值对以查看它们是否为password
或res
和。如果两个条件都为真,则关键字和值将存储在res
中。如果在命令末尾,res
中存储了任何内容,则返回字典:否则返回None
。
答案 2 :(得分:0)
我认为最简单的方法是
set RE {^(username|password)=(.+?)(?:;|$)}
foreach {matched field contents} [regexp -all -inline -line $RE $value] {
puts "I found '$field' which held '$contents'"
}
在您的第一个样本中,这会产生:
I found 'username' which held 'firstuser' I found 'username' which held 'hisuser' I found 'password' which held 'test123'
我们正在使用-all
来匹配每个可能的位置,而不仅仅是第一个位置,-inline
以获取返回的匹配项(因此我们可以foreach
覆盖它们),以及{ {1}}使RE引擎与行上的内容不匹配(影响-line
,.
和^
)。
当一个字段出现两次时,您必须决定该做什么,但不再匹配,而是解析到更高级别的概念。< / p>