73

-a-n选项在以下 bashif语句中执行什么功能?

if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
    REFNAME=$(basename $3)
else

-a-n所谓的初选吗?

是否-a file意味着“如果文件存在则为真。”?

4

2 回答 2

181

-a在“and”或“&&”表达式中将两个表达式链接在一起。此选项已弃用

-n检查字符串的长度是否非零。

您可以将测试表达式转换为以下伪代码:

if ( ($1 has nonzero length) and
     ($2 has nonzero length) and
     ($3 has nonzero length) )

该表达式中不检查文件是否存在,只检查参数是否已提供给脚本。

参数-a-n可以在手册页中找到test

man test

运算符[ ... ]通常用作系统的简写,test ...并且可能在您的系统上具有相同的功能。

于 2013-02-15T17:56:13.370 回答
50

吹毛求疵

开关-a-n严格来说不是bash if语句的一部分,因为该if命令不处理这些开关。

什么是初选?

我称它们为“开关”,但bash您链接到的文档与“初级”指的是相同的东西(可能是因为这是讨论布尔表达式的一部分时使用的常用术语)。

背景和文档

In sh scripts if is a command that takes a command as its argument, executes it and tests its return code. If the return code is 0 the block of code following then is executed up until the closing fi or (if supplied) the following else. If the return code was not 0 and an else statement was supplied then the block of code following else is executed up until the closing fi.

You can see this effect by passing if the command true or the command false, which are simple commands that do nothing and return 0 and non-0 respectively.

if true ; then echo true was true ; else echo true was false ; fi
if false ; then echo false was true ; else echo false was false ; fi

In the sample code you provided the command that you're passing to if is [, which is also sometimes known as test. It is this command which takes the switches you're asking about. In bash the test command will be a built-in command; try type [ to learn its type. For built-in commands help will show usage, so also run help [ to see documentation. Your system probably also has a /bin/[ and a /bin/test and if you man test you can see the manuals for those. Although the behavior of the built-in test may not be identical to the behavior documented in the man pages, which is likely more verbose than the simple description you'll get from help [, it will probably describe the behavior of the built-in [ command fairly accurately.

The behavior of -a and -n

Knowing that the command you're running is test we can consult help test or man test and read its usage. This will show that-n tests the following argument and evaluates to true if it is not an empty string.

In the documentation of test you will also see a the switch -e. This switch tests the following argument and evaluates to true if that argument is a file or directory that exists. More useful still is the -f switch which evaluates to true if the following argument exists and is a regular file (as opposed to a directory or a block device, or whatever).

The source of your confusion is probably that there can be two forms of -a: Unary and binary. When -a is used in a unary context, that is with one following argument but no preceding arguments, it treats its argument as a file and tests for its existence, just like the -e switch. However, when -a is used in a binary context, that is with one argument before it and one argument after it, it treats its arguments as other conditions and acts as a boolean AND operator.

In the interests of portability it is important to note that unary -a is a non-standard extension which won't be found in POSIX. It is available in bash and ksh, however, so usage is probably widespread.

Example

cd /tmp
if [ -a test-file ] ; then
    echo 1: test-file exists
else
    echo 1: test-file missing
fi

touch test-file

if [ -a test-file ] ; then
    echo 2: test-file exists
else
    echo 2: test-file missing
fi

var=somerthing
if [ -n "$var" -a -a test-file ] ; then
    echo variable var is not empty and test-file exists
fi
rm -f test-file
于 2013-02-15T18:23:43.330 回答