Bash字符串比较语法

时间:2009-08-06 01:17:47

标签: linux string macos bash comparison

我正在查看一些Debian软件包中的/etc/bash_completion脚本。我有兴趣使用通过特定目录查找的代码(默认情况下为/etc/bash_completion.d/)并获取该目录中的每个文件。

不幸的是,尝试运行脚本会导致Mac OS X版本的bash出错。有问题的行是:

for i in $BASH_COMPLETION_DIR/*; do
    [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|.rpm*) ]] &&
    [ \( -f $i -o -h $i \) -a -r $i ] && . $i
done

具体来说,我的bash(3.2.17)版本在@()构造上窒息。我明白第一个测试的目的是确保我们不会提供任何编辑器交换文件或备份等。我想准确理解@()语法的作用,如果可能的话,如何在我的古老版本的bash上运行类似的东西(同样优雅)。任何人都可以提供见解吗?

1 个答案:

答案 0 :(得分:3)

它只是shell比较的扩展,相当于grep“或”运算符(|)

根据您的bash版本,它可能无法使用,或者您可能必须使用内置extglob设置shopt。请参阅以下会话记录:

    pax@daemonspawn> $ bash --version
        GNU bash, version 3.2.48(21)-release (i686-pc-cygwin)
        Copyright (C) 2007 Free Software Foundation, Inc.
    pax@daemonspawn> echo @(*~|*.pl)
        bash: syntax error near unexpected token '('
    pax@daemonspawn> shopt extglob
        extglob off
    pax@daemonspawn> shopt -s extglob
    pax@daemonspawn> echo @(*~|*.pl)
        qq.pl qq.sh~ xx.pl
    pax@daemonspawn> 

这允许以下工作:

    ?(pattern-list)
        Matches zero or one occurrence of the given patterns
    *(pattern-list)
        Matches zero or more occurrences of the given patterns
    +(pattern-list)
        Matches one or more occurrences of the given patterns
    @(pattern-list)
        Matches one of the given patterns
    !(pattern-list)
        Matches anything except one of the given patterns

如果无法使其与shopt一起使用,您可以使用旧方法生成类似的效果,例如:

    #!/bin/bash
    for i in $BASH_COMPLETION_DIR/*; do
        # Ignore VIM, backup, swp, files with all #'s and install package files.
        # I think that's the right meaning for the '\#*\#' string.
        # I don't know for sure what it's meant to match otherwise.

        echo $i | egrep '~$|\.bak$|\.swp$|^#*#$|\.dpkg|\.rpm' >/dev/null 2>&1
        if [[ $? == 0 ]] ; then
            . $i
        fi
    done

或者,如果有多个复杂的决定可以决定您是否需要它来源,那么您可以使用最初设置为doit的{​​{1}}变量,并将其设置为true(如果有的话)这些条件触发了。例如,以下脚本qq.sh:

    #!/bin/bash
    for i in * ; do
        doit=1

        # Ignore VIM backups.
        echo $i | egrep '~$' >/dev/null 2>&1
        if [[ $? -eq 0 ]] ; then
            doit=0
        fi

        # Ignore Perl files.
        echo $i | egrep '\.pl$' >/dev/null 2>&1
        if [[ $? -eq 0 ]] ; then
            doit=0
        fi

        if [[ ${doit} -eq 1 ]] ; then
            echo Processing $i
        else
            echo Ignoring $i
        fi
    done

在我的主目录中执行此操作:

    Processing Makefile
    Processing binmath.c
    : : : : :
    Processing qq.in
    Ignoring qq.pl    --+
    Processing qq.sh    |
    Ignoring qq.sh~   --+--- see?
    Processing qqin     |
    : : : : :           |
    Ignoring xx.pl    --+