使用命令替换时 Bash 脚本中的命令执行顺序错误

问题描述 投票:0回答:1

目标

我想编写一个 Bash 脚本,其中有两个

.sh
文件:

  • main.sh
    - 主脚本,其中我将下标称为
    subscripts/checksum.sh
    并将其结果写入名为
    checksum
  • 的变量
  • subscripts/checksum.sh
    - 返回比较两个文本文件内容的
    diff
    命令输出的脚本(它们不同,因此在我的示例中
    diff
    命令将始终返回带有一些描述的非零退出代码)

文件结构

$ tree .
.
├── main.sh
└── subscripts
    ├── checksum.sh
    ├── file1.sha512sum.txt
    ├── file1.txt
    ├── file2.sha512sum.txt
    └── file2.txt

2 directories, 6 files

main.sh

#!/bin/bash


set -e

echo "*** Before checksum"
checksum=$(subscripts/checksum.sh)
echo "*** After checksum"
echo "Checksum value: ${checksum}"

subscripts/checksum.sh

#/bin/bash


set -e

checksum1=subscripts/file1.sha512sum.txt
checksum2=subscripts/file2.sha512sum.txt

echo "----- Before diff"
if diff_res=$(diff ${checksum1} ${checksum2})
then
    echo "Checksums are equal."
else
    echo "There is a difference between the checksums."
fi
echo "----- After diff"
echo ${diff_res}

结果(错误)

执行

main.sh
给出以下结果:

*** Before checksum
*** After checksum
Checksum value: ----- Before diff
There is a difference between the checksums.
1c1 < a5f4d3e657ad3ef1b208e16f47b6d766cf3e2f1db8d6b5c0d2bf0573d10eb2fefcc75c9f91d5f4e047fa9a7d00848911477005015052f7005a2b85eeb8c4eabf file1.txt --- > 576bfc364f00634e8227f71fdf379168e4c3ee013da9eae2bdcdb905746b8514a959a9c01a8f11b8ea62a67ba08a3041a46b8065b73bdaad754e1d6153131896 file2.txt
----- After diff
1c1 < a5f4d3e657ad3ef1b208e16f47b6d766cf3e2f1db8d6b5c0d2bf0573d10eb2fefcc75c9f91d5f4e047fa9a7d00848911477005015052f7005a2b85eeb8c4eabf file1.txt --- > 576bfc364f00634e8227f71fdf379168e4c3ee013da9eae2bdcdb905746b8514a959a9c01a8f11b8ea62a67ba08a3041a46b8065b73bdaad754e1d6153131896 file2.txt

似乎

main.sh
中的每个命令都已先运行,然后是
subscripts/checksum.sh
中的命令。这是为什么?我怎样才能得到正确的结果(如下所述)?

我想要得到的正确结果

通过正确的结果,我的意思是打印

*** Before checksum
,然后进入
subscripts/checksum.sh
并执行从第一个到最后一个的所有命令,将所有三个
echo
命令打印到控制台,然后分配
diff_res
的值到
checksum
中的
main.sh
。整个动作应该以最后一个打印结束,即
*** After checksum
。在我的示例中,
checksum
变量应该具有值:

1c1
< a5f4d3e657ad3ef1b208e16f47b6d766cf3e2f1db8d6b5c0d2bf0573d10eb2fefcc75c9f91d5f4e047fa9a7d00848911477005015052f7005a2b85eeb8c4eabf file1.txt
---
> 576bfc364f00634e8227f71fdf379168e4c3ee013da9eae2bdcdb905746b8514a959a9c01a8f11b8ea62a67ba08a3041a46b8065b73bdaad754e1d6153131896 file2.txt
*** Before checksum
----- Before diff
There is a difference between the checksums.
----- After diff
*** After checksum
Checksum value: 1c1
< a5f4d3e657ad3ef1b208e16f47b6d766cf3e2f1db8d6b5c0d2bf0573d10eb2fefcc75c9f91d5f4e047fa9a7d00848911477005015052f7005a2b85eeb8c4eabf file1.txt
---
> 576bfc364f00634e8227f71fdf379168e4c3ee013da9eae2bdcdb905746b8514a959a9c01a8f11b8ea62a67ba08a3041a46b8065b73bdaad754e1d6153131896 file2.txt

bash command-substitution
1个回答
0
投票

如果我理解正确,您希望看到之前/之后的行(忽略其他行)按以下顺序打印:

*** Before checksum
----- Before diff
----- After diff
*** After checksum

但实际上是按这个顺序打印的:

*** Before checksum
*** After checksum
----- Before diff
----- After diff

这是因为你编写 main.sh 的方式。你写了这个:

checksum=$(subscripts/checksum.sh)

这意味着

checksum.sh
的输出,包括
Before diff
After diff
行,不会立即打印。它将存储在一个变量中以便稍后访问。

换句话说,您的代码遵循以下步骤:

  1. 打印
    *** Before checksum
  2. 运行
    checksum.sh
    并存储其输出(输出有
    Before diff
    After diff
  3. 打印
    *** After checksum
  4. 打印
    Checksum value:
  5. 打印步骤 2 中存储的数据。

这就是为什么行的显示顺序与您想要的不同。

如果您希望

checksum.sh
Before diff
After diff
直接打印到终端,而不将这些行存储在变量中,则应该像这样更改
checksum.sh

echo "----- Before diff" >&2
...
echo "----- After diff" >&2

这是有效的,因为默认情况下,所有输出都会发送到 stdout,它可以使用

$()
存储在变量中。但是使用
>&2
将输出发送到 stderr,该输出显示在终端中,而不是由
$()
存储。

© www.soinside.com 2019 - 2024. All rights reserved.