一句话:想要实现检测一个'\'需要在字符串中使用四个'\',即"\\\\"。
一、现象
首先贴一段正常代码,主要实现将文本框中的字符串进行正则匹配筛查出盘符写入表中。
1、输入“A:\”,理论输出“A:\”。
2、输入“A:\\”,理论输出“A:\”。
3、输入“A:\\xxxxxxxx”,理论输出“A:\”。
/*
* Input String:A:\
*/
QString STarg("A:\\");//..此处使用一个'\'会报错,已经暗示字符串反斜杠需要进行转义。
//QRegExp REDisk("[A-Z]:\\");//.. 1.首先使用直接转义,理论上会经过一次转义匹配一个'\',但是输出ng。
//QRegExp REDisk("[A-Z]:[\\]");//.. 2.其次使用字符方式,但是输出ng。
QRegExp REDisk("[A-Z]:\\\\");//.. 3. 正常。
QStringList MainWindow::newRECmp(QString val,QRegExp re)
{
QStringList List;
int pos=0;
List.clear();
while ((pos = re.indexIn(val, pos)) != -1)
{
QString str = re.cap(0);
List.append(str);
pos += re.matchedLength();
}
return List;
}
void MainWindow::on_pushButton_Check_clicked()
{
QString SDataTemp=ui->textEdit_FileArea->toPlainText();
QStringList SLTemp;
SLTemp=SLTemp=newRECmp(SDataTemp,REDisk);
if(!SLTemp.empty())
{
ui->tableWidget->setItem(0,0,new QTableWidgetItem(SLTemp.first()));
qDebug("Write ok.\n");
}
else
qDebug("Write ng.\n");
}
注释已标注,在代码域1.2.与3.三行中,不论使用哪一行编译都是正常的。仅使用1.与2.会导致无正则匹配结果。
二、原因
1、当定义STarg时,若使用如下代码编译器报错:
QString STarg("A:\");//..此处使用一个'\'会报错,已经暗示字符串反斜杠需要进行转义。
error: expected expression
在此时的反斜杠'\'由于后面紧跟双引号’"‘,导致已经在字符串中构成了一组转义,故此句定义缺乏结束双引号导致报错,由此可得出以下结论:
反斜杠’\‘的转义作用的优先级高于字符串结尾标志。
2、因此势必需要在字符串中针对转义字符的使用要对其作用域严格划分,若想要使用反斜杠'\'字符,就需要对反斜杠进行转义,即"\\"。
注意:此处的转义依然停留在QT的字符串使用阶段,与正则无关。
3、关于正则匹配,有其独立的一套严格语法,具体详情可参考AstralWind的博客:Python正则表达式指南以及zxin的博客:最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等,此处不过多赘述。
4、简单来说,正则匹配中会将一个反斜杠'\'与其之后的任意一个字符匹配构成一组转义,所以在输入至正则匹配的内容中,若想要匹配单反斜杠'\' 字符,就要确保输入的内容为"\\"。
综上所述,正则表达式中的一个反斜杠'\',等于正则转义字符串中的"\\",等于输入正则字符串的"\\\\"。经过了两次转义,一次是QT的,一次是正则的。
三、解决办法
1、以1:4的数量比例换算写入反斜杠,用于正则检测一个'\'字符。
QRegExp REDisk("[A-Z]:\\\\");//.. 3. 正常。
2、以限定符方式进行正则匹配,用于正则检测多个'\'字符。
QRegExp REDisk("[A-Z]:(\\\\){1,2}");//.. 3. 正常。
四、备注
这个问题经历了两次转义这是我未曾预料到的,不排除其他平台也有相似情况的可能,查阅了挺多资料都没有说道这个问题以及根本原因,因此在这里记录一下,希望能帮到更多的人。另外,以上涉及到单引号的都是字符,双引号都是字符串,需要注意区分。