211

我正在尝试编写一个包含函数的 bash 脚本,因此当给定一个.tar,等文件时.tar.bz2.tar.gz它使用 tar 和相关开关来解压缩文件。

我正在使用 if elif then 语句来测试文件名以查看它以什么结尾,但我无法使用正则表达式元字符来匹配它。

为了避免不断重写我在命令行中使用“测试”的脚本,我认为下面的语句应该有效,我已经尝试了括号、引号和元字符的所有组合,但仍然失败。

test sed-4.2.2.tar.bz2 = tar\.bz2$; echo $?
(this returns 1, false)

我确信这个问题很简单,我到处都看过,但我不知道该怎么做。有人知道我该怎么做吗?

4

6 回答 6

332

要匹配正则表达式,您需要使用=~运算符。

尝试这个:

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

或者,您可以在运算符中使用通配符(而不是正则表达式)==

[[ sed-4.2.2.tar.bz2 == *tar.bz2 ]] && echo matched

如果可移植性不是问题,我建议使用[[代替[test,因为它更安全、更强大。请参阅test、[ 和 [[ 之间有什么区别?详情。

于 2013-07-02T08:37:37.560 回答
71

执行此操作的函数

extract () {
  if [ -f $1 ] ; then
      case $1 in
          *.tar.bz2)   tar xvjf $1    ;;
          *.tar.gz)    tar xvzf $1    ;;
          *.bz2)       bunzip2 $1     ;;
          *.rar)       rar x $1       ;;
          *.gz)        gunzip $1      ;;
          *.tar)       tar xvf $1     ;;
          *.tbz2)      tar xvjf $1    ;;
          *.tgz)       tar xvzf $1    ;;
          *.zip)       unzip $1       ;;
          *.Z)         uncompress $1  ;;
          *.7z)        7z x $1        ;;
          *)           echo "don't know '$1'..." ;;
      esac
  else
      echo "'$1' is not a valid file!"
  fi
}

其他注意事项

针对上述评论中的水瓶座力量,We need to store the regex on a var

变量 BASH_REMATCH 在匹配表达式后设置,${BASH_REMATCH[n]} 将匹配括号中的第 n 个组,即以下${BASH_REMATCH[1]} = "compressed"${BASH_REMATCH[2]} = ".gz"

if [[ "compressed.gz" =~ ^(.*)(\.[a-z]{1,5})$ ]]; 
then 
  echo ${BASH_REMATCH[2]} ; 
else 
  echo "Not proper format"; 
fi

(上面的正则表达式并不意味着对文件命名和扩展有效,但它适用于示例)

于 2014-12-11T22:50:34.230 回答
21

我没有足够的代表在这里发表评论,所以我提交了一个新的答案来改进 dogbane 的答案。点。在正则表达式中

[[ sed-4.2.2.tar.bz2 =~ tar.bz2$ ]] && echo matched

例如,实际上将匹配任何字符,而不仅仅是 'tar.bz2' 之间的文字点

[[ sed-4.2.2.tar4bz2 =~ tar.bz2$ ]] && echo matched
[[ sed-4.2.2.tar§bz2 =~ tar.bz2$ ]] && echo matched

或任何不需要用“\”转义的东西。严格的语法应该是

[[ sed-4.2.2.tar.bz2 =~ tar\.bz2$ ]] && echo matched

或者您可以更严格,并在正则表达式中包含前一个点:

[[ sed-4.2.2.tar.bz2 =~ \.tar\.bz2$ ]] && echo matched
于 2018-04-13T23:15:23.187 回答
12

由于您使用的是 bash,因此无需为此创建子进程。这是一种完全在 bash 中执行的解决方案:

[[ $TEST =~ ^(.*):\ +(.*)$ ]] && TEST=${BASH_REMATCH[1]}:${BASH_REMATCH[2]}

说明:序列“冒号和一个或多个空格”前后的组由模式匹配运算符存储在 BASH_REMATCH 数组中。

于 2018-08-22T06:10:25.237 回答
2

shopt -s nocasematch

if [[ sed-4.2.2.$LINE =~ (yes|y)$ ]]
 then exit 0 
fi
于 2017-09-30T14:28:49.040 回答
2
if [[ $STR == *pattern* ]]
then
    echo "It is the string!"
else
    echo "It's not him!"
fi

为我工作!GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)

于 2018-09-01T07:59:56.147 回答