我试图从 shell 脚本中理解这一行。我知道这$(..)
意味着运行并将其输出插入到语句中..
找到的位置。$()
但是这些括号之间发生了什么?这是做什么的?这与前面的内容\ls
有什么关系?\
这是\\
两条线的分割吗?\ls
和普通的一样吗ls
?
APPCLASSPATH=$CLASSPATH:$({ \
\ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \
\ls -1 "$VOLTDB_LIB"/*.jar; \
\ls -1 "$VOLTDB_LIB"/extension/*.jar; \
} 2> /dev/null | paste -sd ':' - )
答案1
3 个命令的输出ls
将传递到将paste
它们合并到值中的命令:
$VOLTDB_VOLTDB"/voltdb-*.jar:$VOLTDB_LIB"/*.jar:$VOLTDB_LIB"/extension/*.jar
笔记:变量$VOLTDB_VOLTDB
和$VOLTDB_LIB
将被扩展,并且对于这些命令中的每一个命令,可能有比只有一个文件更多的值ls
。看到*
那里了吗?这是一个通配符,可扩展为左侧 (voltdb-) 和右侧 (.jar) 之间的任何内容。
这些将匹配:
voltdb-1.jar
voltdb-blah.jar
voltdb-12345.jar
然后所有内容都包含在变量中APPCLASSPATH
:
APPCLASSPATH=$CLASSPATH:$VOLTDB_VOLTDB"/voltdb....etc.
粘贴命令
seq
下面是我使用命令生成数字序列 1-10 的示例。
$ seq 10 | paste -sd ':' -
1:2:3:4:5:6:7:8:9:10
您可以看到该paste
命令正在合并输出并用冒号 ( :
) 分隔。
您还可以像这样模仿示例命令:
$ { echo "hi1"; echo "hi2"; echo "hi3"; } | paste -sd ':' -
hi1:hi2:hi3
笔记:to -
the Past 命令告诉它从 STDIN 获取输入并打印输入的每个参数,以:
.
通过不同的开关,paste
还可以根据-
数据后面的数量将数据分成组。
粘贴示例
这是一个带有 2-
的示例。
$ seq 10 | paste - -
1 2
3 4
5 6
7 8
9 10
这是 3-
的。
$ seq 10 | paste - - -
1 2 3
4 5 6
7 8 9
10
所以它告诉每行应该打印paste
多少个参数。paste
但不要混淆,您正在处理的示例只是从 STDIN 获取输入,用空格分隔每个参数,然后打印它,后跟:
.当给出多个-
' 时,您是在告诉paste
您接受参数,一次 2 个,一次 3 个,等等。
一次 2 个参数,用:
' 分隔:
$ seq 10 | paste -d ':' - -
1:2
3:4
5:6
7:8
9:10
$ seq 10 | paste -d ':' - - -
1:2:3
4:5:6
7:8:9
10::
顺便说一句,如果您包含-s
开关,您将告诉您paste
按顺序(串行)获取参数。观察当您在上面的示例之一中使用它时会发生什么。
一次 2 个:
$ seq 10 | paste -sd ':' - -
1:2:3:4:5:6:7:8:9:10
一次 3 个:
$ seq 10 | paste -sd ':' - - -
1:2:3:4:5:6:7:8:9:10
答案2
$(command)
执行命令并替换其输出。
{ list; }
是一个组命令,在当前shell环境中执行多个命令。它与 类似(list)
,但它不创建子 shell。
\command
用于忽略命令的别名,这可能会大大改变命令的预期行为。
行尾\
仅表示该行继续,因此 shell 会将下一行视为当前行的一部分。当从上下文(左括号或引号)中显而易见时,通常没有必要。
答案3
APPCLASSPATH=$CLASSPATH:$({ \ \ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \ \ls -1 "$VOLTDB_LIB"/*.jar; \ \ls -1 "$VOLTDB_LIB"/extension/*.jar; \ } 2> /dev/null | paste -sd ':' - )
\ls
与 类似ls
,只不过 ifls
是别名,反斜杠可防止别名扩展。这保证了ls
使用该命令,而不是使用可能添加不需要的输出的别名,例如分类器后缀 ( -F
)。
这些ls
命令以现有文件名作为参数调用,列出其参数,每行一个。该选项-1
无效,因为 的输出ls
将发送到管道而不是终端。如果ls
接收到的参数不是现有文件的名称,它将在其标准输出上不显示任何内容,而是显示错误。命令中的错误ls
将被重定向到任何地方2> /dev/null
。有两个原因ls
可能会收到不是文件的参数:如果其中一个变量没有引用现有的可读目录,或者没有与通配符模式匹配的文件。无论哪种情况,模式都会以未扩展的方式传递到ls
.
行末尾的反斜杠导致 shell 忽略后面的换行符。它们在这里都没有用,因为在使用它们的每个点上,shell 都需要一个可选的换行符。
大括号 { … } 对命令进行分组。复合命令{ \ls …; \ls …; \ls … ; }
通过管道传输到paste
并将其错误重定向到/dev/null
.
该paste
命令将所有输入行连接在一起:
。它相当于,tr '\n' :
只是它没有:
在末尾添加 a。
命令替换$(…)
导致 的输出paste
被插值到变量APPCLASSPATH
值之后,CLASSPATH
并用冒号分隔两部分。
这是一个简化版本。这与原始版本略有不同,因为如果没有通配符模式匹配任何内容,APPCLASSPATH
则将等于CLASSPATH
没有额外的尾随冒号(这可能是可取的)。
APPCLASSPATH=$CLASSPATH:$(
\ls "$VOLTDB_VOLTDB"/voltdb-*.jar "$VOLTDB_LIB"/*.jar "$VOLTDB_LIB"/extension/*.jar |
tr '\n' :) 2>/dev/null
APPCLASSPATH=${APPCLASSPATH%:}