コマンドが失敗しなかった場合にのみ、a
コマンド結果の最初の単語を私の変数に割り当てたいと思います。func <some_arg>
失敗した場合は文書化する必要があります。
これまで私がしたことは次のとおりです。
func() {
if [[ $1 -eq 1 ]]
then
echo 'hello world'
return 0
fi
echo 'Something wrong has happened!' >> path/to/dev.log
return 2
}
a=$(func 1)
r=$?
if [[ $r -eq 0 ]]
then
a=$(awk '{ print $1 }' <<<"$a")
fi
これは間違いなく機能しますが、変数を2回割り当てるのは好きではありませんa
。
私はこれを試しました:
a=$(func 2 | awk '{ print $1 }') || echo 'Something wrong has happened!' >> path/to/dev.log
しかし、何も記録しません
もっと良い方法がありますか?
答え1
set -o pipefail
以下を使用して、パイプラインの前の部分でエラーを取得できます。
パイプの戻り状態は、最後のコマンドの終了状態です。パイプ故障オプションが有効です。もしパイプ故障有効にすると、パイプの戻り状態は、ゼロ以外の状態で終了した最後の(最も右側の)コマンドの値、またはすべてのコマンドが正常に終了した場合は0です。
$ foo() { [[ "$1" = 1 ]] || return 1; echo "hello world"; }
$ a=$(set -o pipefail; foo 2 | awk '{print $1}' || echo "fail..." >&2)
fail...
しかし、実際にはなぜ2回割り当てることが問題になるのか理解できません。デフォルトでは、コマンドが成功すると取得した値を変更し、コマンドが失敗した場合は無視します。
あるいは、そのロジックを少し圧縮することもできます。
if a=$(foo 1); then
a=${a%% *};
echo "first word of a is '$a'";
# do some work with $a...
else
echo "error..." >&2;
fi
印刷
first word of a is 'hello'
答え2
シェルには、文字列の最初の単語を解析するいくつかの基本的なメソッドがあります。
サフィックスでトリムする -
${a%% *}
位置引数に代入 -
set -- ${a}
結果はにあります$1
。を使用してこれを簡素化できますset -- $(func 1)
。bash
(のみ)配列要素に分割 -a=( $(func 1) )
- 結果はにあります${a[0]}
。
答え3
a
コードの問題の1つは、関数がfunc
ゼロ以外の結果を返しても競合が発生することです。
代わりに:
#!/bin/sh
func () {
if [ "$1" -eq 1 ]; then
echo 'some sort of logging stuff' >>logfile
return 1
fi
echo 'hello world'
}
a="a string"
if b=$( func 0 ); then
a=${b%% *}
fi
printf '1: a = "%s"\n' "$a"
a="a string"
if b=$( func 1 ); then
a=${b%% *}
fi
printf '2: a = "%s"\n' "$a"
これを実行すると
1: a = "hello"
2: a = "a string"
ご覧のとおり、2番目のケースではa
その値が保持されます。