对于以下变量:
var="/path/to/my/document-001_extra.txt"
我只需要/
[斜杠]和_
[下划线]之间的部分。
此外,还需要删除-
[破折号]。
换句话说:document 001
这是我到目前为止所做的:
var="${var##*/}"
var="${var%_*}"
var="${var/-/ }"
工作正常,但我正在寻找一种更紧凑的替代模式,这将使我失去三重var=...
使用sed,awk,cut等可能对此更有意义,但我正在寻找纯粹的bash解决方案。
需要在GNU bash下运行,版本3.2.51(1)-release
答案 0 :(得分:1)
在编辑问题后谈论模式而不是正则表达式时,我现在将向您展示如何实际在bash
中使用正则表达式:)
[[ $var =~ ^.*/(.*)-(.*)_ ]] && var="${BASH_REMATCH[@]:1:2}"
以前遗憾地使用的参数扩展不能嵌套在bash
中(除非您使用了不明智的eval
黑客,即使这样,它也不会比上面的行清楚。)
=~
运算符在左侧的字符串和右侧的正则表达式之间执行匹配。正则表达式中的括号定义匹配组。如果匹配成功,则[[ ... ]]
的退出状态为零,因此执行&&
之后的代码。 (提醒:不要将流程退出状态的“0 =成功,非零=失败”约定与常见的布尔约定“0 = false,1 = true”混淆。)
BASH_REMATCH
是一个数组参数,bash
在成功的正则表达式匹配后设置。数组的第一个元素包含正则表达式匹配的全文;以下每个元素都包含相应捕获组的内容。
${foo[@]:x:y}
参数扩展会生成数组的y
个元素,从索引x
开始。在这种情况下,它只是写${BASH_REMATCH[1]} ${BASH_REMATCH[2]}
的简短方法。 (另外,虽然var=${BASH_REMATCH[*]:1:2}
也会有效,但我倾向于使用@
来强调你几乎总是想在其他地方使用@
代替*
这一事实上下文。)
答案 1 :(得分:0)
以下两种方法都可以正常工作。虽然第二个对错位字符很敏感(如果在最后一个/
之后有-
或_
,它将会失败。
var=$(IFS=_ read s _ <<<"$var"; IFS=-; echo ${s##*/})
var=$(IFS=/-_; a=($var); echo "${a[@]:${#a[@]} - 3:2}")