杰瑞科技汇

Java调用Shell脚本如何传参?

  1. Shell 脚本如何接收参数:从命令行获取参数。
  2. Shell 脚本如何将这些参数传递给 Java 程序:将获取到的参数作为命令的一部分执行。

第一部分:Shell 脚本接收参数

在 Shell 脚本中,你可以通过特殊变量来访问命令行传入的参数,这些变量是 Shell 的内置功能,与 Java 无关。

Java调用Shell脚本如何传参?-图1
(图片来源网络,侵删)
变量 描述 示例
$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

如何运行这个脚本:

  1. 保存为 run.sh
  2. 赋予执行权限:chmod +x run.sh
  3. 运行并传入参数:
    ./run.sh arg1 "arg with space" 3

预期输出:

Java调用Shell脚本如何传参?-图2
(图片来源网络,侵删)
脚本名称: ./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 程序:

  1. 保存为 ArgDemo.java
  2. 编译:javac ArgDemo.java
  3. 直接运行(不带参数):java ArgDemo
  4. 直接运行(带参数):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"
  • 使用 可以确保每个参数都作为一个独立的、带引号的字符串传递,能正确处理包含空格或特殊字符的参数。这是最安全、最推荐的方式。

如何运行整合后的脚本:

  1. 确保 ArgDemo.class 文件在当前目录下。
  2. 保存上面的 Shell 脚本为 run_java.sh
  3. 赋予执行权限:chmod +x run_java.sh
  4. 运行脚本并传入参数:
    ./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 程序。

分享:
扫描分享到社交APP
上一篇
下一篇