【问题标题】:How to use perl to extract text between and look ahead and a look behind string without applying it twice?如何使用 perl 在不应用两次的情况下提取字符串之间的文本并向前看和向后看?
【发布时间】:2020-09-09 10:57:31
【问题描述】:

我目前有一个字符串:

https://drive.google.com/file/d/j2903r293rj092j3r20/view?usp=sharing

我想从中提取j2903r293rj092j3r20。我在 Mac OS 中使用标准 perl 安装。我有

URL="https://drive.google.com/file/d/j2903r293rj092j3r20/view?usp=sharing"
echo $URL | perl -pe 's/https\:\/\/drive.google.com\/file\/d\///g' | perl -pe 's/\/view\?usp=sharing//g'

我将 perl 应用于正面和背面。有没有办法一步一步做到这一点?谢谢

【问题讨论】:

  • 可能是perl -pe 's/.*\/([^\/]+)\/.*/$1/' file,见demo
  • 也许这应该用适当的解析器来解决stackoverflow.com/q/12425393/725418
  • 不要使用正则表达式来解析 URL。这是一个已解决的问题。使用 Perl 自带的 URI 模块。
  • 可能是这种echo 'https://drive.google.com/file/d/j2903r293rj092j3r20/view?usp=sharing' | perl -ne '@parts = split '/' ; print $parts[-2]' -- 输出j2903r293rj092j3r20
  • @PolarBear perl -F/ -lane'print $F[-2]' 更短。但我认为还是使用解析器更好。

标签: regex macos perl uri


【解决方案1】:

在解析 URL 时,最好使用适当的解析器,例如 URI

use strict;
use warnings;
use URI;

my $uri = URI->new("https://drive.google.com/file/d/j2903r293rj092j3r20/view?usp=sharing");
my @path = $uri->path_segments;
print $path[-2];

打印出来:

j2903r293rj092j3r20

我想如果你需要这个单行,它会是这样的:

perl -MURI -lne'$u = URI->new($_); print (( $u->path_segments )[-2])'

【讨论】:

    【解决方案2】:

    当然。

    首先,在这里使用替换运算符 (s/.../.../) 是错误的工具。您可以使用匹配运算符 (m/.../) 来提取您想要的字符串位。

    echo $URL | perl -pe 'm/https\:\/\/drive.google.com\/file\/d\/(\w+)/ and $_ = $1'
    

    在这里,我们使用“捕获括号”将 URL 中 /d/ 后面的“单词字符”字符串(字母数字和下划线)复制到变量 $1 中。然后我们将其复制到$_,因为这是-p 将自动打印的变量。

    但我们可以做得更好。 s/.../.../m/.../ 都允许我们更改分隔符,这样我们就不必转义所有这些斜线。

    echo $URL | perl -pe 'm[https://drive.google.com/file/d/(\w+)] and $_ = $1'
    

    我们可以直接使用print来去掉最后稍微混淆的变量赋值。

    echo $URL | perl -ne 'print m[https://drive.google.com/file/d/(\w+)]'
    

    而且,如果我们知道我们的输入数据总是看起来像当前示例,那么真的没有必要包含这么多的 URL。

    echo $URL | perl -ne 'print m[/d/(\w+)]'
    

    更新:您有一条评论建议您使用URI module 来解析您的字符串。我不相信这特别有用,因为该模块将为您提供 URL 的路径部分,并且您仍然需要提取路径的正确部分。但是,为了完整起见,下面是一个使用该模块的示例:

    echo $URL | perl -MURI -ne 'print +(URI->new($_)->path_segments)[3]'
    

    我们从输入创建一个 URI 对象,并立即调用其path_segments() 方法来获取路径段。我们打印返回的列表的第四个元素。

    【讨论】:

      【解决方案3】:

      既然你用标记了这个问题,我想一个简单的sed这样的命令没什么问题

      echo "$s" | sed -n 's,.*/d/\([^/]*\).*,\1,p'
      

      匹配直到/d/(包括/d/)的所有字符,捕获下一个字符直到第一个/ 或字符串结尾,然后匹配其余字符。替换为第一组的内容并仅打印该值。

      【讨论】:

        【解决方案4】:

        你可以把逗号分隔的两部分放在一个 perl -pe 命令中:

        echo $URL | perl -pe 's/https\:\/\/drive.google.com\/file\/d\///g','s/\/view\?usp=sharing//g'
        

        【讨论】:

        • 虽然逗号分隔列表确实有效,但分号是一种更标准的样式,不太可能混淆人们。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        • 2014-09-09
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 2019-10-23
        相关资源
        最近更新 更多