- Shell 脚本如何接收参数:从命令行获取参数。
- Shell 脚本如何将这些参数传递给 Java 程序:将获取到的参数作为命令的一部分执行。
第一部分:Shell 脚本接收参数
在 Shell 脚本中,你可以通过特殊变量来访问命令行传入的参数,这些变量是 Shell 的内置功能,与 Java 无关。

| 变量 | 描述 | 示例 |
|---|---|---|
$0 |
脚本自身的名称 | ./run.sh |
$1 |
第一个参数 | hello |
$2 |
第二个参数 | world |
$3 |
第三个参数 | 123 |
| 以此类推 | $4, $5, ... |
|
参数的个数(不包括 $0) |
3 |
|
| 所有参数的列表,每个参数都是独立的字符串(用于循环) | "hello" "world" "123" |
|
| 所有参数的列表,合并成一个字符串(用 IFS 的第一个字符分隔) | "hello world 123" |
重要提示:如果参数本身包含空格("my file.txt"),你必须用引号将其括起来,否则 Shell 会将其拆分为多个参数。
示例脚本 (run.sh)
让我们创建一个简单的 Shell 脚本来演示这些变量的用法。
#!/bin/bash # 这是一个 Shell 脚本,用于演示参数传递 echo "脚本名称: $0" echo "第一个参数: $1" echo "第二个参数: $2" echo "第三个参数: $3" echo "------------------------------------" echo "参数总数: $#" echo "所有参数 (使用 \$@): $@" echo "所有参数 (使用 \$*): $*" echo "------------------------------------" # 使用 $@ 循环处理每个参数,这是最安全的方式 echo "循环遍历每个参数:" for arg in "$@" do echo " - 参数: $arg" done
如何运行这个脚本:
- 保存为
run.sh。 - 赋予执行权限:
chmod +x run.sh。 - 运行并传入参数:
./run.sh arg1 "arg with space" 3
预期输出:

脚本名称: ./run.sh
第一个参数: arg1
第二个参数: arg with space
第三个参数: 3
------------------------------------
参数总数: 3
所有参数 (使用 $@): arg1 "arg with space" 3
所有参数 (使用 $*): arg1 "arg with space" 3
------------------------------------
循环遍历每个参数:
- 参数: arg1
- 参数: arg with space
- 参数: 3
第二部分:将参数传递给 Java 程序
我们来看如何将 Shell 脚本收到的参数,原封不动地传递给 Java 程序。
Java 程序如何接收参数
在 Java 程序中,参数通过 main 方法的 String[] args 数组接收,这个数组的顺序和 Shell 脚本中传入的参数顺序完全一致。
示例 Java 程序 (ArgDemo.java)
public class ArgDemo {
public static void main(String[] args) {
System.out.println("Java 程序启动!");
System.out.println("接收到参数个数: " + args.length);
if (args.length == 0) {
System.out.println("没有接收到任何参数。");
return;
}
System.out.println("开始遍历参数:");
for (int i = 0; i < args.length; i++) {
System.out.println(" - 参数 [" + i + "]: " + args[i]);
}
}
}
如何编译和运行 Java 程序:
- 保存为
ArgDemo.java。 - 编译:
javac ArgDemo.java - 直接运行(不带参数):
java ArgDemo - 直接运行(带参数):
java ArgDemo java is fun
第三部分:整合 Shell 脚本与 Java 程序
这是最关键的一步,我们将创建一个 Shell 脚本,它接收参数,然后调用 Java 程序并把这些参数传递过去。
直接传递(最常用)
这是最直接的方法,在调用 java 命令时,直接将 Shell 脚本的参数()追加到 java 命令的后面。
Shell 脚本 (run_java.sh)
#!/bin/bash
# 检查是否至少传了一个参数
if [ "$#" -eq 0 ]; then
echo "用法: $0 <参数1> <参数2> ..."
exit 1
fi
echo "通过 Shell 脚本调用 Java 程序..."
echo "------------------------------------"
# java 命令的格式是: java [选项] 类名 [参数...]
# 我们将 $@ 放在最后,将所有参数传递给 Java 程序
java ArgDemo "$@"
echo "------------------------------------"
echo "Java 程序执行完毕。"
*为什么用 而不是 `$`?**
java ArgDemo $@会被 Shell 解释为java ArgDemo arg1 "arg with space" 3。java ArgDemo "$@"会被解释为java ArgDemo "arg1" "arg with space" "3"。- 使用 可以确保每个参数都作为一个独立的、带引号的字符串传递,能正确处理包含空格或特殊字符的参数。这是最安全、最推荐的方式。
如何运行整合后的脚本:
- 确保
ArgDemo.class文件在当前目录下。 - 保存上面的 Shell 脚本为
run_java.sh。 - 赋予执行权限:
chmod +x run_java.sh。 - 运行脚本并传入参数:
./run_java.sh hello "world of java" 100
预期输出:
通过 Shell 脚本调用 Java 程序...
------------------------------------
Java 程序启动!
接收到参数个数: 3
开始遍历参数:
- 参数 [0]: hello
- 参数 [1]: world of java
- 参数 [2]: 100
------------------------------------
Java 程序执行完毕。
显式循环传递(不常用,但有助于理解)
你也可以通过循环来逐个构建 java 命令的参数。
#!/bin/bash
if [ "$#" -eq 0 ]; then
echo "用法: $0 <参数1> <参数2> ..."
exit 1
fi
echo "通过循环调用 Java 程序..."
echo "------------------------------------"
# 构建一个变量来存放所有参数
java_args=""
for arg in "$@"
do
# 为每个参数加上引号并追加到变量中,中间用空格隔开
java_args="$java_args \"$arg\""
done
# 执行命令
echo "执行的命令是: java ArgDemo $java_args"
java ArgDemo $java_args
echo "------------------------------------"
echo "Java 程序执行完毕。"
这种方法更复杂,容易出错,不推荐在实际生产中使用,但它能帮助你理解参数是如何被组装的。
高级用法:传递带空格的文件路径
这是一个非常常见的场景,假设你想让 Java 程序读取一个文件,而这个文件名可能包含空格。
Java 程序 (FileReader.java)
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class FileReader {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("请提供一个文件路径作为参数。");
return;
}
String filePath = args[0];
System.out.println("尝试读取文件: " + filePath);
try (BufferedReader reader = new BufferedReader(new java.io.FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("无法读取文件: " + e.getMessage());
}
}
}
Shell 脚本 (read_file.sh)
#!/bin/bash
# 假设你有一个名为 "my test file.txt" 的文件
# 你必须用引号将文件路径括起来传给脚本
if [ "$#" -ne 1 ]; then
echo "用法: $0 \"<文件路径>\""
exit 1
fi
file_path="$1"
echo "准备读取文件: $file_path"
# 同样,使用 "$@" 来安全地传递参数
java FileReader "$file_path"
运行方式:
# 创建一个测试文件 echo "这是第一行。" > "my test file.txt" echo "这是第二行。" >> "my test file.txt" # 运行脚本 ./read_file.sh "my test file.txt"
预期输出:
准备读取文件: my test file.txt
尝试读取文件: my test file.txt
这是第一行。
这是第二行。
| 任务 | Shell 语法 | Java 语法 | 关键点 |
|---|---|---|---|
| 获取参数 | $1, $2, , |
args.length, args[i] |
Shell 用 循环,Java 用 for 循环 |
| 传递参数 | java MyProgram "$@" |
main(String[] args) |
必须使用 来正确处理带空格的参数 |
| 传递文件路径 | ./script.sh "my file.txt" |
args[0] 获取完整路径 |
文件路径必须用引号括起来传给 Shell 脚本 |
记住这个核心模式:你的程序 "$@",这个模式可以安全地将任意数量的参数(包括带空格的)从 Shell 传递给任何命令,包括 Java 程序。
