在perl中使用正则表达式在字符串中查找年份

在perl中使用正则表达式在字符串中查找年份,perl,Perl,input.txt Ken, Robert. (1994). Lessons from Hull House for the contemporary urban university 2008. Social Service Review, 68(3), 299-321. Robert, John. 1994. Lessons from Hull House for the contemporary urban university 2008. Social Service Review.

input.txt

Ken, Robert. (1994). Lessons from Hull House for the contemporary urban university 2008. Social Service Review, 68(3), 299-321.

Robert, John. 1994. Lessons from Hull House for the contemporary urban university 2008. Social Service Review.
Output.txt

Ken, Robert. (<y>1994</y>). Lessons from Hull House for the contemporary urban university 2008. Social Service Review, 68(3), 299-321.

Robert, John. <y>1994</y>. Lessons from Hull House for the contemporary urban university 2008. Social Service Review.
罗伯特,肯。(1994). 2008年当代城市大学赫尔学院的课程。《社会服务评论》,68(3),299-321。 罗伯特,约翰。19942008年当代城市大学赫尔学院的课程。社会服务检讨。 我已经尝试了以下编码,但是我在最近几次得到了标签 有人能告诉我解决办法吗

print "Enter the exp file name without extension: ";
chomp($filename = <STDIN>);
open(RED, "$filename.txt") || die "Could not open EXP file";
open(WRIT, ">$filename.html");

while(<RED>) {
    if(/(.+)(\d{4})/) {
        s/(.+)(\d{4})/$1<y>$2<\/y>/g;
    }
print WRIT $_;
}
close(RED);
close(WRIT);
print“输入exp文件名,不带扩展名:”;
chomp($filename=);
打开(红色,“$filename.txt”)| | die“无法打开EXP文件”;
打开(写“>$filename.html”);
while(){
if(/(.+)(\d{4})/){
s/(.+)(\d{4})/$1$2/g;
}
打印写入$;
}
关闭(红色);
关闭(令状);

您有贪婪的正则表达式,所以只有去年的每一行匹配<代码>?使
+
量词不贪婪(尽可能不匹配)

if(/(.+?)(\d{4})/){
s/(.+?)(\d{4})/$1$2/g;
}
作为旁注,您可以使用

s/(\d{4})/<y>$1<\/y>/g;
s/(\d{4})/$1/g;

您有贪婪的正则表达式,所以只有去年的每一行匹配<代码>?使
+
量词不贪婪(尽可能不匹配)

if(/(.+?)(\d{4})/){
s/(.+?)(\d{4})/$1$2/g;
}
作为旁注,您可以使用

s/(\d{4})/<y>$1<\/y>/g;
s/(\d{4})/$1/g;

你会被正则表达式匹配的贪婪所绊倒。这意味着:
+
正在尽其所能地抓住一切,只剩下足够完成第二个匹配

因此,它只能在以下情况下工作一次:

Ken, Robert. (1994). Lessons from Hull House for the contemporary urban university 2008. Social Service Review, 68(3), 299-321.
+
将匹配到
2008
(包括
(1994)
)的所有内容

您需要使用非贪婪匹配。如中所述:

因此,请尝试:

(.+?)(\d{4})
编辑:如注释中所述。捕获
(.+)
是多余的。这是有条件的。因此,代码如下所示:

while (<DATA>) {
    s/(\d{4})/<y>$1<\/y>/g;
    print;
}

__DATA__
Ken, Robert. (1994). Lessons from Hull House for the contemporary urban university 2008. Social Service Review, 68(3), 299-321.
Robert, John. 1994. Lessons from Hull House for the contemporary urban university 2008. Social Service Review.
while(){
s/(\d{4})/$1/g;
印刷品;
}
__资料__
肯,罗伯特。(1994). 2008年当代城市大学赫尔学院的课程。《社会服务评论》,68(3),299-321。
罗伯特,约翰。19942008年当代城市大学赫尔学院的课程。社会服务检讨。
此外:

  • 启用
    use strict
    使用警告
    
  • 小心
    打开
    根据用户输入打开文件。如果你不提高你的投入,那是很危险的
  • 3参数
    open
    无论如何都是个好主意
让您感到困惑的是正则表达式匹配是贪婪的。这意味着:
+
正在尽其所能地抓住一切,只剩下足够完成第二个匹配

因此,它只能在以下情况下工作一次:

Ken, Robert. (1994). Lessons from Hull House for the contemporary urban university 2008. Social Service Review, 68(3), 299-321.
+
将匹配到
2008
(包括
(1994)
)的所有内容

您需要使用非贪婪匹配。如中所述:

因此,请尝试:

(.+?)(\d{4})
编辑:如注释中所述。捕获
(.+)
是多余的。这是有条件的。因此,代码如下所示:

while (<DATA>) {
    s/(\d{4})/<y>$1<\/y>/g;
    print;
}

__DATA__
Ken, Robert. (1994). Lessons from Hull House for the contemporary urban university 2008. Social Service Review, 68(3), 299-321.
Robert, John. 1994. Lessons from Hull House for the contemporary urban university 2008. Social Service Review.
while(){
s/(\d{4})/$1/g;
印刷品;
}
__资料__
肯,罗伯特。(1994). 2008年当代城市大学赫尔学院的课程。《社会服务评论》,68(3),299-321。
罗伯特,约翰。19942008年当代城市大学赫尔学院的课程。社会服务检讨。
此外:

  • 启用
    use strict
    使用警告
    
  • 小心
    打开
    根据用户输入打开文件。如果你不提高你的投入,那是很危险的
  • 3参数
    open
    无论如何都是个好主意
      没有必要先匹配一年,然后替换它

      不需要捕获不匹配的内容

      然而,有必要确保你谈论的是合法的年份——四位数长的年份,可能也在上个世纪或本世纪

      最简单的说法当然是你永远不想使用的方式:

      # DO NOT USE THIS: IT IS ILLEGIBLE!!
      s{(\b(?=19|20)\d{4}\b)}{<y>$1</y>}g;
      
      或者,如果您运行的是Perl v5.14或更高版本,则可以使用
      /a
      选项:

      s{
          (?<YEAR>            # save in named buffer "year"
              \b              # word-break
              (?= 19 | 20)    # next two chars must be either 19 or 20
              \d{4}           # the year proper
              \b              # word break
          )                   # end of named capture "year"
      }{
          "<y>"       .
          $+{YEAR}    .
          "</y>"
      }egxa;
      
      s{
      (?#保存在命名缓冲区“年”
      \断字
      (?=19 | 20)#接下来的两个字符必须是19或20
      \d{4}本年度
      \断字
      )#命名捕获“年”结束
      }{
      ""       .
      $+{YEAR}。
      ""
      }egxa;
      

      如果您决定其他世纪适用,则可以很容易地修改限制允许哪些世纪的前瞻性。

      无需先匹配一年,然后替换它

      不需要捕获不匹配的内容

      然而,有必要确保你谈论的是合法的年份——四位数长的年份,可能也在上个世纪或本世纪

      最简单的说法当然是你永远不想使用的方式:

      # DO NOT USE THIS: IT IS ILLEGIBLE!!
      s{(\b(?=19|20)\d{4}\b)}{<y>$1</y>}g;
      
      或者,如果您运行的是Perl v5.14或更高版本,则可以使用
      /a
      选项:

      s{
          (?<YEAR>            # save in named buffer "year"
              \b              # word-break
              (?= 19 | 20)    # next two chars must be either 19 or 20
              \d{4}           # the year proper
              \b              # word break
          )                   # end of named capture "year"
      }{
          "<y>"       .
          $+{YEAR}    .
          "</y>"
      }egxa;
      
      s{
      (?#保存在命名缓冲区“年”
      \断字
      (?=19 | 20)#接下来的两个字符必须是19或20
      \d{4}本年度
      \断字
      )#命名捕获“年”结束
      }{
      ""       .
      $+{YEAR}。
      ""
      }egxa;
      

      如果您决定其他世纪适用,则很容易修改限制允许哪些世纪的前瞻性。

      还需要注意的是1)您不必使用
      If
      语句,因为它内置在
      s//
      中,仅在匹配时替换,2)没有锚,
      (.+?)
      将尽可能少地匹配,换句话说:1个字符,几乎不值得努力,最重要的是:3)捕获任何东西