grep returns 没有匹配以下表达式

grep returns no matches for following expression

(?<=_)(.*)(?=\.) 正则表达式与 23353_test.txt 测试字符串一起使用 return 与带有 -p 选项的 grep 无关。它也不显示错误。我希望 return 得到测试。但是当在 regex101.com 中尝试正则表达式时它运行正确。

下面的GNUgrep命令提取正确的子字符串:

grep -oP '(?<=_).*(?=\.)' file

注意 .* 贪婪地匹配,如果你想确保匹配最近的 _. 之间的子字符串,你需要使用

grep -oP '(?<=_)[^._]*(?=\.)' file

其中 [^._]* 匹配除 ._.

以外的零个或多个字符

如果你不能依赖你的grep,你可以在这里使用sed

sed -n 's/.*_\(.*\)\..*//p' file

参见 online demo:

#!/bin/bash
s='23353_test.txt'
grep -oP '(?<=_)(.*)(?=\.)' <<< "$s"
# => test
sed -n 's/.*_\(.*\)\..*//p' <<< "$s"
# => test

第一个解决方案: 您应该使用 awk 满足此要求,请尝试按照您显示的示例进行操作。将字段分隔符设置为 _. 并检查条件是否字段数为 3 然后在此处打印第二个字段。

s='23353_test.txt'
echo "$s" | awk -F'[_.]' 'NF==3{print }'


第二个解决方案: 在此处使用 sed 程序并使用 sed 的捕获组功能。使用 -E 选项在 sed 中启用 ERE,然后在主程序中使用正则表达式 ^[^_]*_([^.]*)\..*,匹配从开始到第一次出现 _ 并创建第一个也是唯一的捕获组_. 之间的所有内容以及匹配文字 . 直到行尾的所有内容。然后用第一个捕获组值替换整行。

s='23353_test.txt'
echo "$s" | sed -E 's/^[^_]*_([^.]*)\..*//'


第三个解决方案: Using GNU awk using awk's match function here .在 match 函数中使用正则表达式来匹配第一次出现的 _ 直到 . 出现并将它放在捕获组中,我们使用名为 arr 的数组来存储捕获的值在其中,因此通过 arr[1] 在其中打印第一个捕获组值。

echo "$s" | awk 'match([=12=],/^[^_]*_([^.]*)\..*$/,arr){print arr[1]}'


第四个解决方案: 这里使用 GNU grep,这里使用它的 -o-P 选项。其中 -o 选项仅用于打印匹配部分,-P 标志用于启用 PCRE 正则表达式。这是以下正则表达式的 Online demo

echo "$s" | grep -oP '^.*?_\K([^.]*)(?=\.\S+$)'