我正在 Go 中創建一個決議 Solidity 代碼的專案。在我的專案中,我創建了一個函式analyzeFile(),它會為每個智能合約 (.sol) 檢測正則運算式的靜態問題:
func analyzeFile(issues []Issue, file string) (map[string][]Finding, error) {
findings := make(map[string][]Finding)
readFile, err := os.Open(file)
if err != nil {
return nil, err
}
defer readFile.Close()
contents, _ := ioutil.ReadFile(file)
scanner := bufio.NewScanner(readFile)
lineNumber := 0
for scanner.Scan() {
lineNumber
line := scanner.Text()
for _, issue := range issues {
if issue.ParsingMode == "SingleLine" {
matched, _ := regexp.MatchString(issue.Pattern, line)
if matched {
findings[issue.Identifier] = append(findings[issue.Identifier], Finding{
IssueIdentifier: issue.Identifier,
File: file,
LineNumber: lineNumber,
LineContent: strings.TrimSpace(line),
})
}
}
}
}
當正則運算式必須在一行上控制代碼時,一切都很好。但是,我還需要檢查多行出現的 .sol 檔案中的內容,例如檢測這段代碼:
require(
_disputeID < disputeCount &&
disputes[_disputeID].status == Status.Active,
"Disputes::!Resolvable"
);
我嘗試在 analyzeFile() 函式中添加以下代碼:
contents, _ := ioutil.ReadFile(file)
for _, issue := range issues {
if issue.ParsingMode == "MultiLine" {
contents_to_string := string(contents)
//s := strings.ReplaceAll(contents_to_string, "\n", " ")
//sr := strings.ReplaceAll(s, "\r", " ")
r := regexp.MustCompile(`((require)([(])\n.*[&&](?s)(.*?)([;]))`)
finds := r.FindStringSubmatch(contents_to_string)
for _, find := range finds {
findings[issue.Identifier] = append(findings[issue.Identifier], Finding{
IssueIdentifier: issue.Identifier,
File: file,
LineContent: (find),
})
}
}
}
但是我得到了錯誤的結果,因為在將源代碼轉換為字串時,我將所有代碼放在一行中,并帶有換行符 \n 字符,這會使任何正則運算式檢查崩潰。
uj5u.com熱心網友回復:
圍繞解決方案的一個詞可以將整個字串與多行拆分為\nafter caputer 組(?s)require\((.*?)\);
func main() {
var re = regexp.MustCompile(`(?s)require\((.*?)\);`)
var str = `require(
_disputeID < disputeCount &&
disputes[_disputeID].status == Status.Active,
"Disputes::!Resolvable"
);`
matches := re.FindAllStringSubmatch(str, -1)
for _, match := range matches {
lines := strings.Split(match[1], "\n")
for _, line := range lines {
fmt.Println(line)
}
}
}
https://go.dev/play/p/Omn5ULHun_-
為了匹配多行,(?m)^[^\S\r\n]*(.*)[^\S\r\n](\S )$可以使用 。我們可以對和之間的內容進行多行require(匹配)
func main() {
var re = regexp.MustCompile(`(?s)require\((.*?)\);`)
var str = `require(
_disputeID < disputeCount &&
disputes[_disputeID].status == Status.Active,
"Disputes::!Resolvable"
);`
var multilineRe = regexp.MustCompile(`(?m)^[^\S\r\n]*(.*)[^\S\r\n](\S )$`)
matches := re.FindAllStringSubmatch(str, -1)
for _, match := range matches {
submathes := multilineRe.FindAllStringSubmatch(match[1], -1)
for _, submatch := range submathes {
fmt.Println(submatch[0])
}
}
}
https://go.dev/play/p/LJsVy5vN6Ej
uj5u.com熱心網友回復:
通過修改我設法讓它作業的代碼:
contents, _ := ioutil.ReadFile(file)
for _, issue := range issues {
if issue.ParsingMode == "MultiLineG015" {
str := string(contents)
var re = regexp.MustCompile(`(?s)require\((.*?)\);`)
//var multilineRe = regexp.MustCompile(`(?m)^[^\S\r\n]*(.*)[^\S\r\n](\S )$`)
//Getting all require in the sol file
matches := re.FindAllStringSubmatch(str, -1)
r := regexp.MustCompile(issue.Pattern)
for _, match := range matches {
submatches := r.FindAllStringSubmatch(match[0], -1)
for _, submatch := range submatches {
findings[issue.Identifier] = append(findings[issue.Identifier], Finding{
IssueIdentifier: issue.Identifier,
File: file,
LineContent: ([]string{submatch[0]}),
})
}
}
這是輸出:
2022-08-rigor\contracts\Community.sol::0 => [(
_lendingNeeded >= _communityProject.totalLent &&
_lendingNeeded <= IProject(_project).projectCost(),
"Community::invalid lending"
);]
2022-08-rigor\contracts\Disputes.sol::0 => [(
_disputeID < disputeCount &&
disputes[_disputeID].status == Status.Active,
"Disputes::!Resolvable"
);]
2022-08-rigor\contracts\Disputes.sol::0 => [(
_actionType > 0 && _actionType <= uint8(ActionType.TaskPay),
"Disputes::!ActionType"
);]
2022-08-rigor\contracts\Project.sol::0 => [(
_sender == builder || _sender == homeFi.communityContract(),
"Project::!Builder&&!Community"
);]
感謝zangw的幫助!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/518003.html
標籤:正则表达式去解析多行
