首先是一些反饋,並對你在十分鐘內寫出這段代碼表示讚賞:
-
(?<=\p{L}) => 這部分很好,但我建議將「字母」包含在實際的捕獲組中,這樣用戶就能看到正則表達式在哪裡發現了潛在的「句尾」。讚賞你同時考慮了大寫和小寫字母。因此,在我的建議中,我將 ?<= 替換為 ?:
-
(?<!\\[\w+]) => 我認為為了避免某些標記造成的誤報,這部分必須位於你的「字母」左側。此外,+ 應該放在方括號外,因為許多標記包含多個字符,例如 \s1。
-
某些標記包含 *,例如表示某事物結束的 \em*。我模糊地記得某些標記可以甚至必須包含 +。如果是這樣,你可以輕鬆地在字符列表中添加這些字符,例如 [\w*+]。
-
\s*(?:\\\w+)?\s* => 我將這部分替換為「跳過節結尾與下一節開頭之間任意數量的潛在標記和空白字符」。
-
\\v [\d\w]+ \p{Lu} => 尋找一個節,其後緊跟一個大寫字母。看來你對 \v 與節號之間以及節號之後的「標準空格」很有信心,所以我保留了該語法。
我想提交一個修改後的正則表達式,不聲稱這是最終解決方案,只是希望能涵蓋更多情況:
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}
以下是我的正則表達式的說明,來自我的工具:
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}選項:不區分大小寫;精確間距;點號匹配換行符
-
斷言在此位置反向匹配下方的正則表達式是不可能的(負向前瞻/negative lookbehind)
- 匹配反斜杠字符
-
匹配下列列表中存在的單個字符
- 一個「單詞字符」(Unicode;任何字母或表意文字、數字、字母數字、連接符號)
- 字面字符 “*”
-
匹配下方的正則表達式
- 匹配 Unicode 類別「字母」中的字符(任何語言的任何類型的字母)
-
匹配單個「空白字符」(任何 Unicode 分隔符、製表符、換行符、回車符、垂直製表符、換頁符、下一行、零寬空格)
-
匹配下方的正則表達式
- 匹配反斜杠字符
-
匹配下列列表中存在的單個字符
- 一個「單詞字符」(Unicode;任何字母或表意文字、數字、字母數字、連接符號)
- 字面字符 “*”
-
匹配單個「空白字符」(任何 Unicode 分隔符、製表符、換行符、回車符、垂直製表符、換頁符、下一行、零寬空格)
- 匹配反斜杠字符
- 字面匹配字符字符串 “v ”(不區分大小寫)
-
匹配下列列表中存在的單個字符
- 一個「數字」(任何 Unicode 文字中的任何十進制數字)
- 一個「單詞字符」(Unicode;任何字母或表意文字、數字、字母數字、連接符號)
- 字面匹配字符 “ ”
- 匹配 Unicode 類別「大寫字母」中的字符(具有小寫變體的大寫字母)
這裡是一些我用於測試的樣本文本。很可能不完整(在每個示例的結尾,我標記了它是否被捕獲):
\v 8 Some text without \em punctuation\em* \rem \any \v 9 A new verse which is a new sentence, starting with a capital. [catch]
\v 8 Some text without \em punctuation\em* \v 9 A new verse which is a new sentence, starting with a capital. [catch]
\v 8 Some text without punctuation \v 9a A new verse which is a new sentence, starting with a capital. [catch]
\v 8 Some text with proper \em punctuation.\em* \just \one \more \v 9 A new verse which is a new sentence, starting with a capital. [punctuation present, so no catch]
\v 8 Some text ending an an all-cap word like \em LORD\em* \v 9 A new verse which is a new sentence, starting with a capital. [catch]
\v 10 A long sentence \whatever \v 11a over two verses or more. [No punctuation needed, so no catch]
所以,這很有趣。希望我沒有偏離太遠。遺憾的是,我永遠記不清 PT 使用的是哪種正則表達式方言(flavour)。如果因為方言不同而導致語法問題,我可以輕鬆地應用另一種方言(如 .NET 或 Java)並重新運行我的工具。
再次強調:這不是解決方案,但或許有助於開啟對話。
希望對你有幫助(hth)
First some feedback, with compliments for writing that in ten minutes:
-
(?<=\p{L}) => Is good, but I propose to include “the letter” in the actual catch, so that the user will see where the regex spotted a potential “end of sentence”. Compliments for catching upper case and lower case letters. So I replace ?<= with ?: in my proposal.
-
(?<!\\[\w+]) => I believe for your intension to avoid false positives with some marker, this part has to be to the left of your “letter”. Also the + should be outside the square brackets as many markers have multiple characters like \s1.
-
And certain markers include the *, for example end-of-something like \em*. I vaguely remember that certain markers can or must even include +. If that is the case, you can easily add to the list of characters like [\w*+].
-
\s*(?:\\\w+)?\s* => This one I replace with "skip over any number of potential markers and any whitespace between the end of the verse and the start of the next verse.
-
\\v [\d\w]+ \p{Lu} => Find a verse followed by an upper-case letter. Seems you are confident here about a “classic space” between \v and the verse number and after the verse number, so I kept that syntax.
I would like to submit a modified regex, not claiming it is the final solution, just hopefully covering more cases:
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}
Here is the blurb for my regex, as per my tool:
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}
(?<!\\[\w\*]*)(?:\p{L})\s*(?:\\[\w\*]+\s+)*\\v [\d\w]+ \p{Lu}Options: Case insensitive; Exact spacing; Dot matches line breaks
-
Assert that it is impossible to match the regex below backwards at this position (negative lookbehind)
- Match the backslash character
-
Match a single character present in the list below
- Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
- A “word character” (Unicode; any letter or ideograph, digit, letter number, connector punctuation)
- The literal character “*”
-
Match the regular expression below
- Match a character from the Unicode category “letter” (any kind of letter from any language)
-
Match a single character that is a “whitespace character” (any Unicode separator, tab, line feed, carriage return, vertical tab, form feed, next line, zero-width space)
- Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
-
Match the regular expression below
- Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
- Match the backslash character
-
Match a single character present in the list below
- Between one and unlimited times, as many times as possible, giving back as needed (greedy)
- A “word character” (Unicode; any letter or ideograph, digit, letter number, connector punctuation)
- The literal character “*”
-
Match a single character that is a “whitespace character” (any Unicode separator, tab, line feed, carriage return, vertical tab, form feed, next line, zero-width space)
- Between one and unlimited times, as many times as possible, giving back as needed (greedy)
- Match the backslash character
- Match the character string “v ” literally (case insensitive)
-
Match a single character present in the list below
- Between one and unlimited times, as many times as possible, giving back as needed (greedy)
- A “digit” (any decimal number in any Unicode script)
- A “word character” (Unicode; any letter or ideograph, digit, letter number, connector punctuation)
- Match the character “ ” literally
- Match a character from the Unicode category “uppercase letter” (an uppercase letter that has a lowercase variant)
And here is some sample text, that I used for testing. Most likely incomplete (at the end of each example, I mark, whether it is a catch or not):
\v 8 Some text without \em punctuation\em* \rem \any \v 9 A new verse which is a new sentence, starting with a capital. [catch]
\v 8 Some text without \em punctuation\em* \v 9 A new verse which is a new sentence, starting with a capital. [catch]
\v 8 Some text without punctuation \v 9a A new verse which is a new sentence, starting with a capital. [catch]
\v 8 Some text with proper \em punctuation.\em* \just \one \more \v 9 A new verse which is a new sentence, starting with a capital. [punctuation present, so no catch]
\v 8 Some text ending an an all-cap word like \em LORD\em* \v 9 A new verse which is a new sentence, starting with a capital. [catch]
\v 10 A long sentence \whatever \v 11a over two verses or more. [No punctuation needed, so no catch]
So, this was fun. Hope I am not too far off. I can sadly never remember what regex-flavour PT uses. If there are issues with syntax because of flavours, I could easily apply a different one like .NET or Java and re-run my tool.
Again: Not the solution but maybe useful to get a dialog going.
hth
機器翻譯自 English