シェルで動的に生成されたif elif elseステートメントを評価する方法

シェルで動的に生成されたif elif elseステートメントを評価する方法

動的に生成されたシェル関数を正しく評価できません。 (評価とは「eval」コマンドを意味します。)

これは、実行時に評価される必須ステートメントです(出力がevalによって実行/評価される場合を除く)。

$ package_check_repo_printf
if [ $(printf '%s\n' "found ${treelistnew0[@]}" | grep -i -e ^"$1") ]
    then
    url=$POOL0$1
    ftp=$ftpPOOL0$1
    echo $1 found in $POOL0
elif [ $(printf '%s\n' "found ${treelistnew1[@]}" | grep -i -e ^"$1") ]
    then
    url=$POOL1$1
    ftp=$ftpPOOL1$1
    echo $1 found in $POOL1
else
    echo $1 not found
fi

そのコードは次のとおりです。

package_check_repo_printf() {
for i in ${!REPOS[@]}
    do
if [[ $ifgen == "" ]]
then
printf '%s' "if [ \$(printf '%s\n' \"found \${treelistnew0[@]}\" | grep -i -e ^\"\$1\") ]
    then
    url=\$POOL0\$1
    ftp=\$ftpPOOL0\$1
    echo \$1 found in \$POOL0
"
ifgen=gen
else
printf '%s' "elif [ \$(printf '%s\n' \"found \${treelistnew$i[@]}\" | grep -i -e ^\"\$1\") ]
    then
    url=\$POOL$i\$1
    ftp=\$ftpPOOL$i\$1
    echo \$1 found in \$POOL$i
"
fi
done
printf '%s' "else
    echo \$1 not found
fi"
}

すべてのprintf '%s'をevalに置き換えると、次の結果が表示されます。

package_check_repo_eval() {
set -v
for i in ${!REPOS[@]}
    do
if [[ $ifgen == "" ]]
then
eval "if [ \$(printf '%s\n' \"found \${treelistnew0[@]}\" | grep -i -e ^\"\$1\") ]
    then
    url=\$POOL0\$1
    ftp=\$ftpPOOL0\$1
    echo \$1 found in \$POOL0
"
ifgen=gen
else
eval "elif [ \$(printf '%s\n' \"found \${treelistnew$i[@]}\" | grep -i -e ^\"\$1\") ]
    then
    url=\$POOL$i\$1
    ftp=\$ftpPOOL$i\$1
    echo \$1 found in \$POOL$i
"
fi
done
eval "else
    echo \$1 not found
fi"
set +v
}

そしてその出力(これは正しいです。printfが行を印刷しないので、set -vが実行された行をエコーするので、package_check_repo_printfの出力と同じでなければなりません):

[chakra@chakra-pc UPM]$ unset ifgen
[chakra@chakra-pc UPM]$ package_check_repo_eval
if [ $(printf '%s\n' "found ${treelistnew0[@]}" | grep -i -e ^"$1") ]
    then
    url=$POOL0$1
    ftp=$ftpPOOL0$1
    echo $1 found in $POOL0
bash: syntax error: unexpected end of file
elif [ $(printf '%s\n' "found ${treelistnew1[@]}" | grep -i -e ^"$1") ]
bash: syntax error near unexpected token `elif'
else
bash: syntax error near unexpected token `else'
[chakra@chakra-pc UPM]$

どうすれば正しく動作させることができますか?

注:明確にすると、私の目標は、この関数をPRINTFベースではなくEVALベースにすることです。

より良い例は次のとおりです(他の方法で実行できるかどうかはわかりませんが、まだ利用可能なif elif elseステートメントを生成します)。

dogs=(1 2 3)
dog=(pink blue white)
colour=(pink black white)
dogs_printf() {
unset ifgen
for i in ${!dogs[@]}
    do
if [[ $ifgen == "" ]]
then
printf '%s' "for i in \${!dogs[@]}
do
if [[ \${dog[i]} == \"\${colour[$i]}\" ]]
    then
    echo dog$i is \"\${colour[$i]}\"
"
ifgen=gen
else
printf '%s' "elif [[ \${dog[i]} == \"\${colour[$i]}\" ]]
    then
    echo dog$i is \"\${colour[$i]}\"
"
fi
done
printf '%s' "else
    echo dog \$i not found
fi
done
"
}
dogs_printf

出力:

[chakra@chakra-pc UPM]$ dogs=(1 2 3)
[chakra@chakra-pc UPM]$ dog=(pink blue white)
[chakra@chakra-pc UPM]$ colour=(pink black white)
[chakra@chakra-pc UPM]$ dogs_printf() {
> unset ifgen
> for i in ${!dogs[@]}
>     do
> if [[ $ifgen == "" ]]
> then
> printf '%s' "for i in \${!dogs[@]}
> do
> if [[ \${dog[i]} == \"\${colour[$i]}\" ]]
>     then
>     echo dog$i is \"\${colour[$i]}\"
> "
> ifgen=gen
> else
> printf '%s' "elif [[ \${dog[i]} == \"\${colour[$i]}\" ]]
>     then
>     echo dog$i is \"\${colour[$i]}\"
> "
> fi
> done
> printf '%s' "else
>     echo dog \$i not found
> fi
> done
> "
> }
[chakra@chakra-pc UPM]$ dogs_printf
for i in ${!dogs[@]}
do
if [[ ${dog[i]} == "${colour[0]}" ]]
    then
    echo dog0 is "${colour[0]}"
elif [[ ${dog[i]} == "${colour[1]}" ]]
    then
    echo dog1 is "${colour[1]}"
elif [[ ${dog[i]} == "${colour[2]}" ]]
    then
    echo dog2 is "${colour[2]}"
else
    echo dog $i not found
fi
done
[chakra@chakra-pc UPM]$ for i in ${!dogs[@]}
> do
> if [[ ${dog[i]} == "${colour[0]}" ]]
>     then
>     echo dog0 is "${colour[0]}"
> elif [[ ${dog[i]} == "${colour[1]}" ]]
>     then
>     echo dog1 is "${colour[1]}"
> elif [[ ${dog[i]} == "${colour[2]}" ]]
>     then
>     echo dog2 is "${colour[2]}"
> else
>     echo dog $i not found
> fi
> done
dog0 is pink
dog 1 not found
dog2 is white
[chakra@chakra-pc UPM]$ 

ベストアンサー1

私はあなたが何を要求するのか完全にはわかりませんが、タイトルの問題を解決する非常に簡単な例(シェルで動的に生成されたifステートメントを評価する方法)は次のとおりです。

#!/bin/bash

# eval_dynamic_if_then

# Get a command to test from the user
COMMAND="$*"

# Construct an if-then statement using the user
# supplied command and save it to a variable
read -r -d '' IF_THEN <<HEREDOC
if eval "${COMMAND}"; then
  echo "Command successful!"
else
  echo "Command NOT successful!"
fi
HEREDOC

# Evaluate the command
eval "${IF_THEN}"

以下は、このスクリプトの呼び出しの例です。

./eval_dynamic_if_then true

これにより、次のような出力が生成されます。

Command successful!

または:

./dynamic_if_then false

生産する:

Command NOT successful!

を使用しようとしているので、printfコマンドを評価するのではなく、コマンドのみを印刷する調整方法は次のとおりです。

#!/bin/bash

# print_dynamic_if_then

# Get a command to test from the user
COMMAND="$*"

# Construct an if-then statement using the user
# supplied command and save it to a variable
read -r -d '' IF_THEN <<HEREDOC
if eval "${COMMAND}"; then
  echo "Command successful!"
else
  echo "Command NOT successful!"
fi
HEREDOC

# Print the command
printf "${IF_THEN}"

このスクリプトの出力を評価するには、次の手順を実行します。

eval "$(print_dynamic_if_then true)"

代替項目が引用されています。たとえば、次は機能しません。

eval $(print_dynamic_if_then true)

これにより、次のエラーメッセージが表示されます。

-bash: syntax error: unexpected end of file

元の例を見ると、渡された引数文字列が完全なシェルステートメントではなくコードスニペットであるステートメントでステートメントを置き換えるように見えますprintfevalこの特定の問題に対する解決策は、実行するステートメントをコマンドに渡す前にステートメント全体を生成することですeval

また、このアプローチに反対する他のユーザーの意見にも答えたいと思います。私があなたなら、コマンドに頼らずに最終目標を達成する方法を考えてみましょうeval

おすすめ記事