【问题标题】:Regex: Grab second string between two single quotes正则表达式:在两个单引号之间获取第二个字符串
【发布时间】:2020-08-21 13:59:40
【问题描述】:

我可以在以下文本中匹配字符串吗?


默认用户名和密码为“user”和“ZWiliWH8E2mV”。


我正在尝试获取第二组单引号之间的字符串:ZWiliWH8E2mV。这个字符串是随机生成的,我只能依赖格式,而不是 ZWiliWH8E2mV。经过一番谷歌搜索,我可以将其与 grep 匹配:

cat file_name | grep -oP "(?<=').*?(?=')"

但这是第三场比赛,我不知道如何从那里开始。如果其他工具更适合我正在尝试做的事情,我愿意使用它们,但我不是很精通它们。

【问题讨论】:

  • 密码中会不会也有单引号?
  • grep -oP ".*'\\K[^']+(?=')" file_name,见demo
  • Wiktor 的解决方案对我有用。密码中不会有单引号。感谢您的帮助。

标签: regex grep


【解决方案1】:

我正在尝试获取第二组单引号之间的字符串

使用awk,可以避免正则表达式:

s="The default username and password is 'user' and 'ZWiliWH8E2mV'."

awk -F "'" '{print $4}' <<< "$s"
ZWiliWH8E2mV

这里我们使用' 作为字段分隔符,awk 中的第 4 个字段将给我们用单引号括起来的第 2 个值。

【讨论】:

    【解决方案2】:

    正如您在问题中所述,您正在尝试获取第二组单引号之间的字符串,您可以匹配前 3 个单引号并在其后开始匹配,直到出现第四个单引号。

    negated character class [^']+ 匹配除单引号之外的任何字符。

    ^(?:[^']+'){3}\K[^']+(?=')
    

    说明

    • ^ 字符串开始
    • ?:[^']+'){3}' 匹配除 ' 以外的任何字符 3 次,然后匹配 '
    • \K 清除匹配缓冲区(在此之前忘记匹配的内容)
    • [^']+ 匹配除' 以外的任何字符的 1 次以上(您要匹配的内容)
    • (?=') 正向前瞻,断言右边是'

    Regex demo | Bash demo

    更新后的代码可能如下所示

    cat file_name | grep -oP "^(?:[^']+'){3}\K[^']+(?=')"
    

    【讨论】:

    • 这是一个很棒的正则表达式,感谢您在这里详细分享。
    【解决方案3】:

    您可以使用grep 获取最后两个单引号之间的值:

    grep -oP ".*'\\K[^']+(?=')" file_name
    

    online demo

    -o 选项仅输出匹配的子字符串,P 使 grep 使用 PCRE 正则表达式引擎。

    PCRE 正则表达式详细信息

    • .* - 除换行符以外的任何 0 个或多个字符,尽可能多
    • ' - 一个 ' 字符
    • \K - 匹配重置操作符,丢弃目前在整个匹配内存缓冲区中匹配的所有文本
    • [^']+ - 除了' 字符之外的一个或多个字符
    • (?=') - 一个积极的前瞻,确保在当前位置的右侧有一个 ' 字符。

    【讨论】:

      【解决方案4】:

      如果您有多个单引号字段:

      $ s="'first' and 'second' and 'third' and 'fourth' and the rest"
      

      你可以使用下面的 Perl 一行来获取nth 字段:

      echo "$s" |
      perl -lne 'while (/[\x27]([^\x27]*)[\x27]/g) {print $1 if ++$i==3}'
      
      # third
      

      因此,对于您的示例,密码是第二个引用字段:

      echo "The default username and password is 'user' and 'ZWiliWH8E2mV'." |
      perl -lne 'while (/[\x27]([^\x27]*)[\x27]/g) {print $1 if ++$i==2}'
      

      打印:

      ZWiliWH8E2mV
      

      您还可以使用 gawk 并将 FPAT 设置为相同的正则表达式来打印第 n 个字段:

      s="'first' and 'second' and 'third' and 'fourth' and the rest"
      
      echo "$s" |
      gawk -v n=2 'BEGIN{FPAT="[\x27][^\x27]*[\x27]"} 
                  { gsub(/[\x27]/,"",$n); print $n}'
      
      # second
      

      或者您可以使用两个 GNU sed 命令的管道,其中 n 是您在第二个 sed 中打印的行:

      echo "$s" |
      gsed -E 's/[^\x27]*\x27([^\x27]*)\x27[^\x27]*/\1\n/g' | gsed -nE '4p'
      # fourth
      

      注意:

      [\x27]' 的十六进制字符表示。大多数正则表达式实现都支持十六进制字符表示,但不是全部。例如 POSIX sed 是狡猾的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-25
        • 2019-05-07
        • 1970-01-01
        相关资源
        最近更新 更多