【问题标题】:extract a substring of 11 characters from a line using sed,awk or perl使用 sed、awk 或 perl 从一行中提取 11 个字符的子字符串
【发布时间】:2012-10-30 12:56:14
【问题描述】:

我有一个文件,每一行都有很多行 有子字符串

whatever_blablablalsfjlsdjf;asdfjlds;f/watch?v=yPrg-JN50sw&amp,whatever_blabla

whatever_blablabla"/watch?v=yPrg-JN50sw&amp" class=whatever_blablablavwhate

我想提取一个子字符串,比如上面的“yPrg-JN50s”

匹配模式是 字符串 "/watch?="

后面的 11 个字符

如何提取子串

希望是sed,awk在一行 如果没有,pn 行 perl 脚本也可以

【问题讨论】:

  • ITYM /watch?v=,而不是 /watch?=。另外,该字符串可以在一行中出现多次吗?

标签: perl shell sed awk


【解决方案1】:

你可以的

grep -oP '(?<=/watch\?v=).{11}'

如果您的 grep 知道 Perl 正则表达式,或者

sed 's/.*\/watch?v=\(.\{11\}\).*/\1/g'

【讨论】:

  • 如上一行,您的脚本无法获取“0_NfNAL3Ffc”,因为 (?=&amp) 不是通用的
  • @user1769686:你为什么不把这个包含在你原来的问题中?请edit您的问题包含此输入。
【解决方案2】:
$ cat file
/watch?v=yPrg-JN50sw&amp
"/watch?v=yPrg-JN50sw&amp" class=
$
$ awk 'match($0,/\/watch\?v=/) { print substr($0,RSTART+RLENGTH,11) }' file
yPrg-JN50sw
yPrg-JN50sw

【讨论】:

    【解决方案3】:

    只用shell的参数扩展,提取“watch?v=”后面的11个字符:

    while IFS= read -r line; do
        tmp=${line##*watch?v=}
        echo ${tmp:0:11}
    done < filename
    

    【讨论】:

      【解决方案4】:

      您可以使用 sed 删除无关信息:

      sed 's/[^=]\+=//; s/&.*$//' file
      

      或者使用 awk 和合理的字段分隔符:

      awk -F '[=&]' '{print $2}' file
      

      file的内容:

      cat <<EOF > file
      /watch?v=yPrg-JN50sw&amp
      "/watch?v=yPrg-JN50sw&amp" class=
      EOF
      

      输出:

      yPrg-JN50sw
      yPrg-JN50sw
      

      编辑以适应 cmets 中提到的新要求

      cat <<EOF > file
      <div id="" yt-grid-box "><div class="yt-lockup-thumbnail"><a href="/watch?v=0_NfNAL3Ffc" class="ux-thumb-wrap yt-uix-sessionlink yt-uix-contextlink contains-addto result-item-thumb" data-sessionlink="ved=CAMQwBs%3D&amp;ei=CPTsy8bhqLMCFRR0fAodowXbww%3D%3D"><span class="video-thumb ux-thumb yt-thumb-default-185 "><span class="yt-thumb-clip"><span class="yt-thumb-clip-inner"><img src="//i1.ytimg.com/vi/0_NfNAL3Ffc/mqdefault.jpg" alt="Miniature" width="185" ><span class="vertical-align"></span></span></span></span><span class="video-time">5:15</span> 
      EOF
      

      将 awk 与合理的记录分隔符一起使用:

      awk -v RS='[=&"]' '/watch/ { getline; print }' file
      

      注意,您应该为此类任务使用适当的 XML 解析器。

      【讨论】:

      • 您应该注意,将 RS 设置为多个字符会使其特定于 GNU awk。其他 awk 通常不会抱怨,它们只是不起作用。
      • @EdMorton:很好,很笨拙,但是是的,这有可移植性问题。
      【解决方案5】:
      grep --perl-regexp --only-matching --regexp="(?<=/watch\\?=)([^&]{0,11})"
      

      【讨论】:

        【解决方案6】:

        假设您的行与您引用的格式完全相同,这应该可以工作。

        awk '{print substr($0,10,11)}'
        

        编辑:从另一个答案的评论中,我猜你的行比这更长更复杂,在这种情况下需要更全面的东西:

        gawk '{if(match($0, "/watch\\?v=(\\w+)",a)) print a[1]}'
        

        【讨论】:

        • 大多数 awks 不支持 \w。我怀疑它是特定于 GNU awk 的。
        • GNU awk 构成了绝大多数 awk,不是吗?但我会更改名称以使其明确。
        • 没有。大多数 UNIX 机器没有安装 GNU awk,它们带有 nawk、mawk、/usr/xpg4/bin/awk 或其他。
        猜你喜欢
        相关资源
        最近更新 更多
        热门标签