我正在学习bash脚本的正则表达式。但是,当我测试字符串匹配时,行始终无法通过。这是我正在测试的内容:
我有一个txt文件,其中包含“歌曲”列表:
$ cat soundtrack.txt
Ludwig Van Beethoven - 01 - Allero.oog
Ludwig Van Beethoven - 02 - Adag.mp3
Ludwig Van Beethoven - 03 - Beach.oog
Ludwig Van Beethoven - 04 - Caven Adven.wmv
我想使用Regex来获取数字的“曲目号”。
这是脚本:
$ cat soundtrack.sh
#!/bin/bash
IFS=$'\n'
for CD in `cat soundtrack.txt`
do
if [[ "$CD" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]
then
echo "Found ${BASH_REMATCH[2]}"
fi
done
但是,bash调试显示字符串无法匹配正则表达式:
$ bash -x soundtrack.sh
+ IFS='
'
++ cat soundtrack.txt
+ for CD in '`cat soundtrack.txt`'
+ [[ Ludwig Van Beethoven - 01 - Allero.oog =~ \(\[\[:alpha:]\[:blank:]]\*\)- \(\[\[:digit:]]\*\) - \(\.\*\)\$ ]]
+ for CD in '`cat soundtrack.txt`'
+ [[ Ludwig Van Beethoven - 02 - Adag.mp3 =~ \(\[\[:alpha:]\[:blank:]]\*\)- \(\[\[:digit:]]\*\) - \(\.\*\)\$ ]]
+ for CD in '`cat soundtrack.txt`'
+ [[ Ludwig Van Beethoven - 03 - Beach.oog =~ \(\[\[:alpha:]\[:blank:]]\*\)- \(\[\[:digit:]]\*\) - \(\.\*\)\$ ]]
+ for CD in '`cat soundtrack.txt`'
+ [[ Ludwig Van Beethoven - 04 - Caven Adven.wmv =~ \(\[\[:alpha:]\[:blank:]]\*\)- \(\[\[:digit:]]\*\) - \(\.\*\)\$ ]]
但是,如果我直接在外壳中使用相同的表达式进行测试,那么它将起作用:
$ if [[ "Ludwig Van Beethoven - 01 - Allero.oog" =~ ([[:alpha:][:blank:]]*)-\ ([[:digit:]]*)\ -\ (.*)$ ]]; then echo yes; else echo no; fi
yes
我的脚本出了什么问题?我是否必须添加额外的配额或反斜杠?只是对我没有意义。
P.S。
$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
答案 0 :(得分:1)
要注意的是,这些东西并不相同:
[[ "$CD" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]
[[ "$CD" =~ ([[:alpha:][:blank:]]*)-\ ([[:digit:]]*)\ -\ (.*)$ ]]
第一个版本是您在脚本中的编写方式,第二个版本是在shell中运行的方式。
也就是说,如果您将模式双引号,那么将按字面意义使用正则表达式符号。您不能将模式用双引号引起来。
答案 1 :(得分:1)
问题是您引用的正则表达式会占用所有特殊的正则表达式功能:仅引用文字位,尤其是如果它们是空格。第二个问题是您正在使用for循环读取文件:don't do that
while IFS= read -r CD; do
if [[ "$CD" =~ ([[:alpha:][:blank:]]*)"- "([[:digit:]]*)" - "(.*) ]]
then
echo "Found ${BASH_REMATCH[2]}"
fi
done < soundtrack.txt