gpt4 book ai didi

bash - 从 Grep RegEx 中捕获组

转载 作者:行者123 更新时间:2023-11-29 08:37:02 26 4
gpt4 key购买 nike

我在 sh (Mac OSX 10.6) 中有这个小脚本来查看一组文件。谷歌此时已停止提供帮助:

files="*.jpg"
for f in $files
do
echo $f | grep -oEi '[0-9]+_([a-z]+)_[0-9a-z]*'
name=$?
echo $name
done

到目前为止(很明显,对你们这些 shell 专家来说)$name 仅包含 0、1 或 2,这取决于 grep 是否发现文件名与提供的内容匹配。 我想要的是捕获括号 ([a-z]+) 中的内容并将其存储到变量

如果可能的话,我希望仅使用grep。如果不是,请不要使用 Python 或 Perl 等。sed 或类似的东西 – 我想从 *nix 纯粹主义者的角度来攻击它。

此外,作为一个 super 酷的奖励,我很好奇如何在 shell 中连接字符串?我抓到的组是$name里存的字符串“somename”,我想在它的末尾加上字符串“.jpg”,可以cat $name '.jpg'吗?

最佳答案

如果你使用 Bash,你甚至不必使用 grep :

files="*.jpg"
regex="[0-9]+_([a-z]+)_[0-9a-z]*"
for f in $files # unquoted in order to allow the glob to expand
do
if [[ $f =~ $regex ]]
then
name="${BASH_REMATCH[1]}"
echo "${name}.jpg" # concatenate strings
name="${name}.jpg" # same thing stored in a variable
else
echo "$f doesn't match" >&2 # this could get noisy if there are a lot of non-matching files
fi
done

最好将正则表达式放在变量中。如果按字面意思包含,某些模式将不起作用。

这使用 =~这是 Bash 的正则表达式匹配运算符。匹配结果保存到名为 $BASH_REMATCH 的数组中.第一个捕获组存储在索引 1 中,第二个(如果有的话)存储在索引 2 中,依此类推。索引零是完全匹配。

您应该知道,如果没有 anchor ,此正则表达式(以及使用 grep 的正则表达式)将匹配以下任何示例以及更多示例,这可能不是您要查找的内容:

123_abc_d4e5
xyz123_abc_d4e5
123_abc_d4e5.xyz
xyz123_abc_d4e5.xyz

要消除第二个和第四个示例,请像这样制作您的正则表达式:

^[0-9]+_([a-z]+)_[0-9a-z]*

表示字符串必须以一位或多位数字开头。克拉代表字符串的开头。如果您在正则表达式的末尾添加一个美元符号,如下所示:

^[0-9]+_([a-z]+)_[0-9a-z]*$

那么第三个例子也将被删除,因为点不在正则表达式的字符中,美元符号代表字符串的结尾。请注意,第四个示例也未通过此匹配。

如果你有 GNU grep (大约 2.5 或更高版本,我认为,当添加了 \K 运算符时):

name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg

\K运算符(可变长度后视)使前面的模式匹配,但不在结果中包含匹配项。等价的固定长度是 (?<=) - 模式将包含在右括号之前。您必须使用 \K if 量词可能匹配不同长度的字符串(例如 +*{2,4} )。

(?=)运算符匹配固定或可变长度的模式,称为“先行”。它也不在结果中包含匹配的字符串。

为了使匹配不区分大小写,(?i)使用运算符。它会影响跟随它的模式,因此它的位置很重要。

根据文件名中是否有其他字符,可能需要调整正则表达式。您会注意到,在本例中,我展示了一个在捕获子字符串的同时连接字符串的示例。

关于bash - 从 Grep RegEx 中捕获组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1891797/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com