更新された質問

更新された質問

コマンドに渡す必要があるパラメータを動的に変更できるスクリプトがあります(mkvプロパティエディタこの場合)。次のスクリプト例を考えてみましょう。

#!/bin/bash

LANG_NAME="eng lish"

MYSETTINGS=()
MYSETTINGS+=("--edit 1")
MYSETTINGS+=("--set \"language=${LANG_NAME}\"")

echo "Count = ${#MYSETTINGS[@]}" # should be 2
set -x # enable to see the invoked command
mkvpropedit ${MYSETTINGS[@]}

これを実行するとコンソールに入ります。

[~] # ./test.sh
Count = 2
+ mkvpropedit --edit 1 --set '"language=eng' 'lish"'

しかし、私の考えでは一重引用符なしの最終呼び出しmkvプロパティエディタ、このように:

+ mkvpropedit --edit 1 --set "language=eng lish"

私も配列を変数としてエコーしようとしましたが、エコーは一重引用符を削除しましたが、変数を次のように使用できませんでした。mkvプロパティエディタ一重引用符が再び表示されるため...

もちろん、変数が単一の単語(たとえば)の場合でも、スクリプトは機能するはずですLANG_NAME="eng"。私のBashバージョンは3.2です(実際にBusybox)。

更新された質問

おそらく、以下の例は私がやろうとしていることをよりよく説明します。コピーできるように一部の名前を変更しました。

#!/bin/bash

TITLE_NAME="my title"

MYSETTINGS=()
MYSETTINGS+=("--edit track:2")
MYSETTINGS+=("--set \"name=${TITLE_NAME}\"")

set -x
mkvpropedit file.mkv ${MYSETTINGS[@]} 

このスクリプトを実行すると、次の結果が表示されます(誤った参照のため)。

# ./test.sh
+ mkvpropedit file.mkv --edit track:2 --set '"name=my' 'title"'
Error: More than one file name has been given ('file.mkv' and 'title"').

手動で実行する場合:

# mkvpropedit file.mkv --edit track:2 --set "name=my title"
The file is being analyzed.
The changes are written to the file.
Done.

だから、これは私が電話したい参考問題です。mkvプロパティエディタスクリプトで配列を使用します。

使用評価する

現在動作しているように見えるのは、mkvpropeditandをfile.mkv配列に挿入して最終的に呼び出すことです。eval "${MYSETTINGS[@]}"しかし、それは価値があり、安全ですか?いいえeval 邪悪な(ふざけた)?

TITLE_NAME="my title"

MYSETTINGS=(mkvpropedit file.mkv)
MYSETTINGS+=("--edit track:2")
MYSETTINGS+=("--set \"name=${TITLE_NAME}\"")

set -x
eval "${MYSETTINGS[@]}"

返品:

# ./test.sh
+ eval mkvpropedit file.mkv '--edit track:2' '--set "name=my title"'
++ mkvpropedit file.mkv --edit track:2 --set 'name=my title'
The file is being analyzed.
The changes are written to the file.
Done.

答え1

一重引用符なし- これは、使用時の変数の内容に対するシェルの明示的な表現にすぎませんset -xdeclare -p一度に1つの配列要素を使用または印刷して、配列要素を表示していることを確認できます。

LANG_NAME="eng lish"

MYSETTINGS=()
MYSETTINGS+=("--edit 1")
MYSETTINGS+=("--set \"language=${LANG_NAME}\"")

それから

$ declare -p MYSETTINGS
declare -a MYSETTINGS=([0]="--edit 1" [1]="--set \"language=eng lish\"")

または

$ printf '>>>%s<<<\n' "${MYSETTINGS[@]}"
>>>--edit 1<<<
>>>--set "language=eng lish"<<<

しかし、--edit、、、、およびを1別々のトークンとしてコマンドに渡そうとします。--setlanguage=eng lish

  1. 配列の構成中にスペースまたはグローバル文字を含むすべてのトークンを引用しますlanguage="${LANG_NAME}""language=${LANG_NAME}"

  2. 配列拡張を使用する場合の二重引用符(単語の分割とファイル名の生成の防止 - 「split+glob」とも呼ばれる)

だから

LANG_NAME="eng lish"

MYSETTINGS=()
MYSETTINGS+=(--edit 1)
MYSETTINGS+=(--set language="${LANG_NAME}")

それから

mkvpropedit file.mkv "${MYSETTINGS[@]}"

二重引用符は、追加のトークン化なしで各要素を別々の単語に"${name[@]}"拡張するため、変数拡張の周囲に二重引用符を追加する必要はありません。追加の引用符は文字通りコマンドに渡されます。name\"name=${TITLE_NAME}\"

また、見ることができます変数に保存されたコマンドをどのように実行できますか?

答え2

[間違った]ドル記号を脱出してください:

MYSETTINGS+=("--set name=\${TITLE_NAME}")

または:

MYSETTINGS+=('--set name=${TITLE_NAME}')
mkvpropedit file.mkv ${MYSETTINGS[@]}

コマンド実行時に拡張に使用される変数

./test.sh
+ mkvpropedit file.mkv --edit track:2 --set 'name=${TITLE_NAME}'
The file is being analyzed.
The changes are written to the file.
Done.

関連情報