我在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'吗?


当前回答

如果您有bash,您可以使用扩展的globbing

shopt -s extglob
shopt -s nullglob
shopt -s nocaseglob
for file in +([0-9])_+([a-z])_+([a-z0-9]).jpg
do
   IFS="_"
   set -- $file
   echo "This is your captured output : $2"
done

or

ls +([0-9])_+([a-z])_+([a-z0-9]).jpg | while read file
do
   IFS="_"
   set -- $file
   echo "This is your captured output : $2"
done

其他回答

我相信在grep是不可能的

对话:

name=`echo $f | sed -E 's/([0-9]+_([a-z]+)_[0-9a-z]*)|.*/\2/'`

不过,我想尝试一下额外的奖励:

echo "$name.jpg"

这是一个使用gawk的解决方案。这是我发现我需要经常使用的东西,所以我为它创建了一个函数

function regex1 { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'1'}']}'; }

使用just do

$ echo 'hello world' | regex1 'hello\s(.*)'
world

下面的例子展示了如何使用正则表达式捕获组从文件名中提取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,…分别

给你的一个建议-你可以使用参数展开来删除从最后一个下划线开始的部分名称,在开头也是这样:

f=001_abc_0za.jpg
work=${f%_*}
name=${work#*_}

name的值为abc。

查看苹果开发者文档,向前搜索“参数扩展”。

我更喜欢一行的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()
'