我在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是否发现文件名与提供的问题匹配。我想要的是捕获parens ([a-z]+)内的内容并将其存储到一个变量中。
如果可能的话,我只想使用grep。如果不是,请不要使用Python或Perl等sed或类似的语言——我想从*nix纯粹的角度来攻击这个问题。
此外,作为一个超级酷的奖金,我很好奇我如何能在壳串?我捕获的组是存储在$name中的字符串“someename”,我想在它的末尾添加字符串“.jpg”,我可以cat $name '.jpg'吗?
我更喜欢一行的python或perl命令,这两者通常都包含在主要的linux发行版中
echo $'
<a href="http://stackoverflow.com">
</a>
<a href="http://google.com">
</a>
' | python -c $'
import re
import sys
for i in sys.stdin:
g=re.match(r\'.*href="(.*)"\',i);
if g is not None:
print g.group(1)
'
处理文件:
ls *.txt | python -c $'
import sys
import re
for i in sys.stdin:
i=i.strip()
f=open(i,"r")
for j in f:
g=re.match(r\'.*href="(.*)"\',j);
if g is not None:
print g.group(1)
f.close()
'
我意识到这个问题的答案已经被接受了,但从“严格*nix纯粹主义的角度”来看,完成这项工作的正确工具似乎是pcregrep,它似乎还没有被提及。试着改变一下台词:
echo $f | grep -oEi '[0-9]+_([a-z]+)_[0-9a-z]*'
name=$?
致以下:
name=$(echo $f | pcregrep -o1 -Ei '[0-9]+_([a-z]+)_[0-9a-z]*')
仅获取捕获组1的内容。
pcregrep工具利用了您已经在grep中使用过的所有相同语法,但实现了您需要的功能。
如果参数-o是空的,它的工作方式就像grep版本一样,但它也接受pcregrep中的一个数字参数,该参数指示您希望显示哪个捕获组。
使用此解决方案,脚本中需要的更改最少。您只需将一个模块实用程序替换为另一个,并调整参数。
有趣的注意:您可以使用多个-o参数以它们在行上出现的顺序返回多个捕获组。
下面的例子展示了如何使用正则表达式捕获组从文件名中提取3个字符序列:
for f in 123_abc_123.jpg 123_xyz_432.jpg
do
echo "f: " $f
name=$( perl -ne 'if (/[0-9]+_([a-z]+)_[0-9a-z]*/) { print $1 . "\n" }' <<< $f )
echo "name: " $name
done
输出:
f: 123_abc_123.jpg
name: abc
f: 123_xyz_432.jpg
name: xyz
因此,perl中的if-regex条件语句将同时过滤掉所有不匹配的行,对于那些匹配的行,它将应用捕获组(s),您可以使用$1,$2,…分别