在Bash脚本中,正则表达式会失效
我从一个zip文件中提取了一串字符串:
866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg
我想要第一个字段(大小)和路径。
在一个在线正则表达式测试工具中测试时,这给出了我想要的结果:
(^[0-9]+)" "[0-9]{4}-[0-9]{2}-[0-9]{2}" "[0-9]{2}:[0-9]{2}" "(.+)
但当我把它放到脚本里时却没有输出
if [[ $x =~ (^[0-9]+)" "[0-9]{4}-[0-9]{2}-[0-9]{2}" "[0-9]{2}:[0-9]{2}" "(.+) ]]; then
echo bash0 Captured : ${BASH_REMATCH[0]}
echo bash1 Captured number: ${BASH_REMATCH[1]}
echo bash2 Captured NAME: ${BASH_REMATCH[2]}
fi
带有第一项:
if [[ $x =~ (^[0-9]+) ]]; then
它给出数字,但把其余任何部分加上后就没有输出
我需要改动什么才能让它工作?
解决方案
我把你原来的脚本放在 test.sh 里,在 GNU bash, version 5.2.21(1)-release (x86_64-pc-cygwin) 上按预期工作:
x='866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg'
if [[ $x =~ (^[0-9]+)" "[0-9]{4}-[0-9]{2}-[0-9]{2}" "[0-9]{2}:[0-9]{2}" "(.+) ]]; then
echo bash0 Captured : ${BASH_REMATCH[0]}
echo bash1 Captured number: ${BASH_REMATCH[1]}
echo bash2 Captured NAME: ${BASH_REMATCH[2]}
fi
$ bash test.sh
bash0 Captured : 866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg
bash1 Captured number: 866275
bash2 Captured NAME: Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg
为便于阅读,我建议把正则表达式放到一个变量里:
x='866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg'
regex='(^[0-9]+) [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2} (.+)'
if [[ $x =~ $regex ]]; then
echo bash0 Captured : ${BASH_REMATCH[0]}
echo bash1 Captured number: ${BASH_REMATCH[1]}
echo bash2 Captured NAME: ${BASH_REMATCH[2]}
fi
备选方案
看起来问题是在于 " " 在 bash 中。
看起来它把第一个 " 视为 (^[0-9]+) 的结束,第二个 " 视为更长字符串的开头。
我找到了两种方法:
- 使用
\来转义空格,而不是" "
x='866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg'
if [[ $x =~ (^[0-9]+)\ [0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}\ (.+) ]]; then
echo bash0 Captured : ${BASH_REMATCH[0]}
echo bash1 Captured number: ${BASH_REMATCH[1]}
echo bash2 Captured NAME: ${BASH_REMATCH[2]}
fi
- 把所有内容放在
( )里,并使用普通空格而不是" "
但这需要在BASH_REMATCH中改变索引
x='866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg'
if [[ $x =~ ((^[0-9]+) [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2} (.+)) ]]; then
echo bash0 Captured : ${BASH_REMATCH[0]}
echo bash1 Captured number: ${BASH_REMATCH[2]}
echo bash2 Captured NAME: ${BASH_REMATCH[3]}
fi
结果:
bash0 Captured : 866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg
bash1 Captured number: 866275
bash2 Captured NAME: Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg
在以下环境测试:GNU bash 5.2.21,Linux Mint 22(基于Ubuntu 24.04)
用于测试的完整代码:
#!/bin/bash
x='866275 2016-02-06 11:25 Documents/familystuff/Household/Agri Stuff/Sheep/sheep Photos/2014 ewe lambs/074Cleo 6Feb16a.jpg'
echo '--- 1 ---'
if [[ $x =~ ((^[0-9]+) [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2} (.+)) ]]; then
echo bash0 Captured : ${BASH_REMATCH[0]}
echo bash1 Captured : ${BASH_REMATCH[1]}
echo bash2 Captured number: ${BASH_REMATCH[2]}
echo bash3 Captured NAME: ${BASH_REMATCH[3]}
fi
echo '--- 2 ---'
if [[ $x =~ (^[0-9]+)\ [0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}\ (.+) ]]; then
echo bash0 Captured : ${BASH_REMATCH[0]}
echo bash1 Captured number: ${BASH_REMATCH[1]}
echo bash2 Captured NAME: ${BASH_REMATCH[2]}
fi
我在其他Stack Overflow站点也发现了类似的问题
- Stack Overflow: regex - 如何在Bash中用正则表达式匹配空格?
- Unix & Linux: regular expression - Bash regex whitespace before match
也许不完全是同一个问题,但也是寻找帮助的好去处
- Server Fault: 如何在Bash变量中匹配空格
- Super User: bash - Conditional spaces in a regular expression?
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。