正则表达式:抓住两个单引号之间的第二个字符串

问题描述

我可以得到一些帮助,以匹配以下文本中的字符串吗?


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


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

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

但这是第三场比赛,我不确定如何从那里开始。如果其他工具比我想做的更好,我愿意使用其他工具,但是我并不精通这些工具。

解决方法

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

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

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

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

这里我们使用'作为字段定界符,awk中的第4个字段将为我们提供第二个值,并用单引号引起来。

,

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

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

请参见online demo

-o选项仅输出匹配的子字符串,P使grep使用PCRE regex引擎。

PCRE正则表达式详细信息

  • .*-尽可能多的0个或多个除换行符以外的字符
  • '-一个'字符
  • \K-匹配重置操作符,该操作将丢弃到目前为止已在整体匹配存储器缓冲区中匹配的所有文本
  • [^']+-除'字符外的一个或多个字符
  • (?=')-一个积极的前瞻性,可确保在当前位置的右边紧邻有一个'字符。
,

正如您在问题中所说的那样,您试图获取第二组单引号之间的字符串,您可以匹配前三个单引号,并在其后开始匹配,直到出现第四个单引号为止。 / p>

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

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

说明

  • ^字符串的开头
  • ?:[^']+'){3}'匹配除'以外的任意3个字符,然后匹配'
  • \K清除匹配缓冲区(直到此刻为止,忘记匹配的内容)
  • [^']+匹配除'(您要匹配的内容)之外的任意字符1倍以上
  • (?=')正向前进,断言直接在右边的是'

Regex demo | Bash demo

更新后的代码可能如下

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

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

$ 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就是狡猾。