name=$(echo "$FILENAME" | grep -E '*\.(eng|por|pt-BR)\.*')
为什么这条线不起作用?
如果我做
echo "Test (2013).1080p.por.mkv" | grep -E "*\.(eng|por)\.*"
它有效,我在脚本中尝试使用“”而不使用“和使用',但似乎没有通过管道传输到grep。我不知道为什么?我正在使用bash。
FILENAME="Test (2013).1080p.por.mkv"
我只想抓取.por。或文件中的 .eng
答案1
grep
是打印与模式匹配的(整行)行的工具。提取字符串的一部分是不合适的(尽管某些grep
实现具有-o<n>
或-o
在某些情况下可以使用的选项)。
在这里,您可以使用expr
:
name=$(expr " $FILENAME" : '.*\.\(eng\)\.' '|' \
" $FILENAME" : '.*\.\(por\)\.' '|' \
" $FILENAME" : '.*\.\(pt-PT\)\.')
(对于foo.por.eng.bar
, 优先于over eng
)。por
pt-PT
一些expr
实现(例如 GNU)expr
也支持:
name=$(expr " $FILENAME" : '.*\.\(eng\|por\|pt-PT\)\.')
(如果文件名中有多个,则返回最右边的匹配项)
使用 GNUgrep
或兼容:
name=$(
printf '%s\n' "$FILENAME" |
grep -Po '\.\K(eng|por|pt-PT)(?=\.)' |
head -n 1
)
(返回第一个出现的位置,替换head
为tail
最后一个出现的位置)
或者您可以使用 shell 的case
构造而不运行任何命令:
case $FILENAME in
(*.por.*) name=por;;
(*.eng.*) name=eng;;
(*.pt-PT.*) name=pt-PT;;
esac
和bash
:
re='\.(por|eng|pt-PT)\.'
[[ $FILENAME =~ $re ]]
name=${BASH_REMATCH[1]}
(第一次出现。用zsh
,替换BASH_REMATCH
为match
)
答案2
假设文件名类似于Some name.por.mkv
,并且最终扩展名固定,您也可以使用 POSIX shell 字符串操作:
$ echo "$FILENAME"
Test (2013).1080p.por.mkv
$ x=${FILENAME%.mkv}; echo "${x##*.}"
por
在这里,${var%.mkv}
删除尾随.mkv
,并${var##*.}
删除直到(现在)最后一个点的所有内容。您可以通过更改.mkv
为仅更改第一个扩展来处理其他扩展 .*
。