用于将引用字符串拆分为其组件的正则表达式

时间:2016-06-27 16:59:15

标签: javascript regex

使用更合适的示例字符串更新了问题

有这样的字符串:

Name I, Some-Thing A, More BC (2016) Example: A string title. Publication. 12:123-54
Name I, Some-Thing A, More BC, et al. (2016) Example: A string title? Publication. 12:123-54
Name I, Some-Thing A, More BC: Example: A string title. Publication 2016; 12: 123-54
Name I, Some-Thing A, More BC: Example: A string title. Publication 2016; 12: 123
Name I, Some-Thing A, More BC (2016): Example: A string title. Publication 12, 123-54
Name I, Some-Thing A, More BC (2016): Example: A string title. Publication 12 (6), 123-54
Name I, Some-Thing A, More BC: Example: A string title. Publication. 2016 June;12(6):123-54. Ignore this

现在我正在尝试提取它们的部分以获得结果:

1: Name I, Some-Thing A, More BC || Name I, Some-Thing A, More BC, et al.
2: 2016
3: Example: A string title? || Example: A string title
4: Publication
5: 12
6: 123-54 || 123

这是我到目前为止所得到的:

/([\w-]+ [A-Z]{1,3}(?:, [\w-]+ [A-Z]{1,3})*(?:, et al\.)*)|\((\d{4})\)?|([\w:]+[\w ]+(?=\.|\?|$))|(\d+(?=:))|([\d-]+)/g

https://regex101.com/r/wB3wU4/2

感谢 anubhava Jan 到目前为止。

但有了这个我没有得到所有 Publication ,在最后一个字符串中我想忽略pagenumber之后的所有内容,我需要忽略pagenumber前面的括号(如果有的话)一个)。

对我来说,第二个问题是如何使用此数据进行正确处理,因为匹配的位置可能不同。示例:通常匹配[2]应为year,但对于第3个字符串,情况并非如此。所以结果搞得一团糟: - (

6 个答案:

答案 0 :(得分:4)

如果您的示例输入是您通常会遇到的常见字符串的指示符,您可以将此概括一点:

// Split the string based on parentheses, periods, question-marks and colons
// along with any leading or trailing spaces (i.e. trimming)
var matches = input.split(/\s*[().?:]\s*/);

从可读性和维护的角度来看,正则表达式通常是噩梦,所以如果可以简化它们,我会推荐它。

示例

enter image description here

var input = "Name I, Some A, More BC (2016) A string title. Publication. 12:123-54";
var matches = input.split(/\s*[()?.:]\s*/);
for(var i = 0; i < matches.length; i++){
    console.log('[' + i +']:' + ' ' + matches[i]);
}

答案 1 :(得分:2)

你去了:

([^()]+)\((\d+)\)\s*([^.]+)[.\s]*([^.]+)[.\s]*(\d+):([-\d]+)

捕获组编号与您的编号相对应,请参阅a demo on regex101.com

答案 2 :(得分:2)

我把帽子戴在戒指上的时间。这就是我想出的:

^(.*?)\s*(?:\(((?:19|20)\d\d)\)|:)[\s:]*(.*?[?.!])\s*([\w\s]+?)\.?\s*(?:((?:19|20)\d\d)(?:\s+\w+)?)?[.;\s]*(\d+)\s*(?:\(\d+\))?[,:\s]+(\d+(?:-\d+)?)[^\d]*$

See it here at regex101

由于复杂性,我不会尝试在此处解释正则表达式的每一部分,但请检查指向regex101的链接,您将在右侧窗格中看到解释。​​

但我会尝试解释它的要点。这取决于我不确定的一些事实,但是......

从字符串的开头

  • 歌曲标题必须以括号中的一年结束冒号(:)。这限制了一年到二十或二十一世纪的匹配。

然后从后面:

  • 忽略 -part
  • 中没有数字
  • 最后一次捕获始终采用number dash number形式,后面的部分是可选的。
  • 12部分是一个数字,可选地前面有.;或空格,后跟括号内的可选数字。括号可以选择以空格开头。然后整个部分后跟至少一个,:或空格。
  • 12部分可选择以一年开头,然后可选择后跟一个月(扔掉​​)。

在字符串的开头和结尾之间,从第一部分开始,“句子”被捕获以标点符号结尾.?或{{ 1}})。之后是第二个“句子” - !部分。

这为我们提供了以下捕获组:

  1. Title 1
  2. (可选)年
  3. Title 2
  4. 句子Publication
  5. (可选)年
  6. Publication part
  7. 12 part
  8. 即年份在第2组 5。

    感觉非常脆弱,但它可能会为您完成工作。 ;)

    修改

    我做了一个JS剪辑来说明:(使用全屏)

    123-54

    修改

    评论:标题以括号或冒号OR点结束一年。

    我还没有完全掌握不同部分是什么,但我认为在这种情况下它是我们谈论的第一个领域。 (示例中的第三个字段结束“字符串标题”...)其当前表单中的正则表达式处理年份和冒号。因此,要将 dot 添加到字段终止符,您可以将问题var theStrings = [ 'Name I, Some-Thing A, More BC (2016) Example: A string title. Publication. 12:123-54', 'Name I, Some-Thing A, More BC, et al. (2016) Example: A string title? Publication. 12:123-54', 'Name I, Some-Thing A, More BC: Example: A string title. Publication 2016; 12: 123-54', 'Name I, Some-Thing A, More BC: Example: A string title. Publication 2016; 12: 123', 'Name I, Some-Thing A, More BC (2016): Example: A string title. Publication 12, 123-54', 'Name I, Some-Thing A, More BC (2016): Example: A string title. Publication 12 (6), 123-54', 'Name I, Some-Thing A, More BC: Example: A string title. Publication. 2016 June;12(6):123-54. Ignore this', 'Name I, Some-Thing A, More BC (2050) Example: A string title. Placeholder. 55:123-54', 'Name I, Some-Thing A, More BC, et al. (2016) Example: A string title? Word. 22:123-54', 'Name: Example: A string title. Variable 2014; 31: 123-54', 'This can basically be anything!: Example: A string title. Publication 100 2058; 789: 123', 'Name I, Some-Thing A, More BC (1998): Example: A string title. What Ever 4, 123-54', 'Name I, Some-Thing A, More BC (2016): Example: A string title. Journey of 2000 miles 54 (6), 123-54', 'Name I, Some-Thing A, More BC: Example: A string title. Some Words. 1999 June;1(6):123-54. Ignore this' ], re = /^(.*?)\s*(?:\(((?:19|20)\d\d)\)|:)[\s:]*(.*?[?.!])\s*([\w\s]+?)\.?\s*(?:((?:19|20)\d\d)(?:\s+\w+)?)?[.;\s]*(\d+)\s*(?:\(\d+\))?[,:\s]+(\d+(?:-\d+)?)[^\d]*$/, res, i, j output = '<style>caption {background-color: blue; color: white;} th {background-color: lightblue;}</style>'; for (i = 0; i < theStrings.length; i++) { res = theStrings[i].match(re); output += '<table border="1" style="width:100%">'; output += '<tr>'; output += '<caption>The string "' + theStrings[i] + '" ends up as:</caption>'; output += '<tr><th style="width:30%">Title 1</th><th style="width:10%">Year</th><th style="width:30%">Title 2</th><th style="width:10%">Value 4</th><th style="width:10%">Value 5</th><th style="width:10%">Value 6</th></tr>'; output += '<td>' + res[1] + '</td>'; output += '<td>' + (res[2] ? res[2] : res[5]) + '</td>'; output += '<td>' + res[3] + '</td>'; output += '<td>' + res[4] + '</td>'; output += '<td>' + res[6] + '</td>'; output += '<td>' + res[7] + '</td></tr></table><br/>'; } document.write(output);更改为:,允许:

    [:.]

答案 3 :(得分:1)

我使用以下正则表达式:

^([A-Za-z-]+ [A-Z]{1,3}(?:, [A-Za-z-]+ [A-Z]{1,3})*(?:, et al\.)?):? (?:\((\d{4})\):? )?([A-Za-z\:\?\. ]+[A-Za-z\?])\.? ([A-Za-z]+)\.? (?:([0-9]+)[A-Za-z ]*; ?)?(\d+) ?(?:\(\d+\))?[\:,] ?([0-9-]+)

由于year可以在不同的地方进行交换,因此我使用此代码始终获取正确的year

var year = matches[2] || matches[5];

您可以在this fiddle中查看整个脚本。

这个正则表达式会给我以下输出,我认为这些是您正在寻找的:

  

&#39;姓名I,Some A,More BC(2016)字符串标题。插图。 12:123-54&#39;

1: "Name I, Some A, More BC"
2: "2016"
3: "A string title"
4: "Illustration"
5: "12"
6: "123-54"
  

&#39;姓名I,Some-Thing A,更多BC(2016)示例:字符串标题。出版物。 12:123-54&#39;

1: "Name I, Some-Thing A, More BC"
2: "2016"
3: "Example: A string title"
4: "Publication"
5: "12"
6: "123-54"
  

&#39;姓名I,Some-Thing A,More BC,et al。 (2016)示例:字符串标题?出版物。 12:123-54&#39;

1: "Name I, Some-Thing A, More BC, et al."
2: "2016"
3: "Example: A string title?"
4: "Publication"
5: "12"
6: "123-54"
  

&#39;姓名I,Some-Thing A,更多BC:示例:字符串标题。插图2016; 12:123-54&#39;

1: "Name I, Some-Thing A, More BC"
2: "2016"
3: "Example: A string title"
4: "Illustration"
5: "12"
6: "123-54"
  

&#39;姓名I,Some-Thing A,更多BC:示例:字符串标题。 2016年出版物; 12:123&#39;

1: "Name I, Some-Thing A, More BC"
2: "2016"
3: "Example: A string title"
4: "Publication"
5: "12"
6: "123"
  

&#39;姓名I,Some-Thing A,更多BC(2016):示例:字符串标题。出版物12,123-54&#39;

1: "Name I, Some-Thing A, More BC"
2: "2016"
3: "Example: A string title"
4: "Publication"
5: "12"
6: "123-54"
  

&#39;姓名I,Some-Thing A,更多BC(2016):示例:字符串标题。出版物12(6),123-54&#39;

1: "Name I, Some-Thing A, More BC"
2: "2016"
3: "Example: A string title"
4: "Publication"
5: "12"
6: "123-54"
  

&#39;姓名I,Some-Thing A,更多BC:示例:字符串标题。出版物。 2016年6月; 12(6):123-54。忽略这个&#39;

1: "Name I, Some-Thing A, More BC"
2: "2016"
3: "Example: A string title"
4: "Publication"
5: "12"
6: "123-54"

答案 4 :(得分:0)

您可以使用这个笨拙的正则表达式捕获各种组件:

/^((?:,? *[A-Za-z.-]+ [A-Za-z]{1,3})+)[ :.,]+(?:\((\d+)\)[ :]+)?([a-zA-Z]+: [a-zA-Z ]+[?]?)[. ]+([A-Za-z]+)[. ;\dA-Za-z]+?(\d+)(?:[:,]| *\()[: \d,)]*?(\d+(?:-\d+)?)(?:[ .]|$)/gm

RegEx Demo

答案 5 :(得分:0)

更新#1

有很多答案,所以我也应该提供一些比较

你对我有什么用?

^([\w-]+ [A-Z]{1,3}(?:, [\w-]+ [a-zA-Z]{1,3}\.?)*)[ :](?:\((\d+)\)| ?([\w]+)):? ?([ \w]+)[.:?]? ?([ \w]+)?[.:?]? ?([A-Za-z]+)?[.:?]? ?([\d]+) ?([a-zA-Z]+)?[,;:]? ?(?:\(([\d-]+)\),?|([\d-]+)):? ?(?:\((\d+)\)[,:]|([\d-]+))? ?([\d-]+)?

仅供参考,它的长度为232个字符。

有效吗?

如果输入与原始帖子中的输入类似,或者如您在某些评论中所述的那样指定,则确实有效。 Live demo

如此冗长,它被称为真正的RegEx?

我不认为它是正则表达式。它使用语法,但不仅仅是编程if / else条件。这就像爬梯子可能有一些破碎的梯级。但这是解决问题所需的一种方式。

我为什么要选择你的?

我不知道。这是你的选择。但是我会对满足您需求的答案进行基准测试。

  • 输入字符串:
Name I, Some-Thing A, More BC (2016) Example: A string title. Publication. 12:123-54
Name I, Some-Thing A, More BC, et al. (2016) Example: A string title? Publication. 12:123-54
Name I, Some-Thing A, More BC: Example: A string title. Publication 2016; 12: 123-54
Name I, Some-Thing A, More BC: Example: A string title. Publication 2016; 12: 123
Name I, Some-Thing A, More BC (2016): Example: A string title. Publication 12, 123-54
Name I, Some-Thing A, More BC (2016): Example: A string title. Publication 12 (6), 123-54
Name I, Some-Thing A, More BC: Example: A string title. Publication. 2016 June;12(6):123-54. Ignore this
Name I, Some-Thing A, More BC (2050) Example: A string title. Placeholder. 55:123-54
Name I, Some-Thing A, More BC, et al. (2016) Example: A string title? Word. 22:123-54
  • 迭代次数:50 x 1000

  • 标志:multi-line

结果:

@ HiDeo的RegEx:

Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   9

Elapsed Time:    10.75 s,   10753.42 ms,   10753415 µs

@ anubhava的RegEx:

Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   9

Elapsed Time:    9.28 s,   9277.62 ms,   9277621 µs

@ ClasG&#39; RegEx:

Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   9

Elapsed Time:    8.86 s,   8864.05 ms,   8864050 µs

@ revo的RegEx:

Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   9

Elapsed Time:    7.02 s,   7024.97 ms,   7024972 µs

如图所示,所有表演时间都非常接近。所以你不会很难选择一个。

感谢@sln节省时间和最近我开始合作的精彩软件RegexFormat