Bash関数/スクリプト引数が変数に完全にコピーされました。

Bash関数/スクリプト引数が変数に完全にコピーされました。

'(他の文字も可能です)変数に保持できないので、Bash関数/スクリプト引数を変数に完全にコピーするにはどうすればよいですか?
例えば

m() {
 v="$@"
 echo "$v"
}

$ m let it be 'foo' bar
let it be foo bar

心からお世話になりありがとうございます。よろしくお願いします。

ベストアンサー1

ここで注目すべき点は、例えば実行時です。

m let it be 'foo bar'

プログラムはmコマンドライン全体を取得しませんが、シェルはまずコマンドラインを解析して引用符、変数拡張などを処理します。このコマンドの最終結果は、個々の文字列の配列に似ています(この場合は[ let、、、、] )。itbefoo bar

同様に、

f="James Matthew"
l="Bond"
m "$l, $f $l"

m[]のみBond, James Matthew Bondが表示され、関連する変数と引用符は不明です。

これは、通常のプログラムが元の入力ラインにアクセスできないことを意味します。


zshにはプリランハンドラの解決策がありますエスケープや引用なしで拡張シェルを閉じる方法はありますか?そしてzsh:シェル制御文字を含むコマンドラインのみをエコーするエイリアスまたはシェル関数しかし、Bashを見たことがないようです。

最も近いのは、DEBUG拡張、参照処理、およびリダイレクトの前に実行されるコマンドを表示するトラップです。ただし、一度に1つの単純なコマンドしか表示されないため、完全ではありません。コメントは表示される前に削除され、引用符で囲まれていない、、、、、または;(少なくとも)コメントは解析され続けます。&|&&||()

とにかく、私たちは次のことを試すことができます:

#!/bin/bash

shopt -s extdebug

handle_@ () {
    local re='[[:space:]]*@ ([^[:space:]]+)[[:space:]]+(.*)'
    if [[ $BASH_COMMAND =~ $re ]]; then
        "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
        return 1
    fi
}
m() {
    printf "<%s>\n" "$1"
}

trap handle_@ DEBUG

@ m 'foo bar' doo "$var" > /dev/null
@ m what about this?; date
@ m or some (parentheses)?

スクリプトはDEBUGトラップを使用して始まるコマンドを検出し、スペース@ で区切られた後に「単語」を実行するコマンドとして使用し、残りを単一の引数として渡します。トラップハンドラから戻ると、1シェルが実際に通常の方法でコマンドを実行しないように指示するため、エラーメッセージが表示されず、埋め込み拡張は実行されません(extdebug設定が必要です)。

出力は次のようになり、dateその後にセミコロンがあり、括弧が構文を破ることを示しています。

<'foo bar' doo "$var" > /dev/null>
<what about this?>
Sun Sep 18 18:39:38 EEST 2022
debugprint.sh: line 20: syntax error near unexpected token `('
debugprint.sh: line 20: `@ m or some (parentheses)?'

正直に言うと、少し逆重なり、特殊文字の制限はかなりランダムであり、スクリプトに他の問題がないことを保証することはできません。


通常、これを実用的な用途に使用する予定の場合は、プログラムの構造を考え直し、実行している作業に応じて、ファイルやたとえばドキュメントを使用して文字列を取得することをお勧めします。

ここでは、次のコマンドを使用していますが、生の文字列を比較的簡単に入力できますstdin

m() {
    m=$(cat) 
    printf "<%s>\n" "$m"
}
m <<'EOF'
Say "$hello" to my 'little friend'
EOF

その後、印刷

<Say "$hello" to my 'little friend'>

here-docで区切られた文字列(in <<'EOF')を使用すると、引用符を気にせずに任意のテキストと文字を入れることができます。 (もちろん、区切り文字列自体を除いて、代わりにランダムに生成された文字列を使用できますEOF。)

おすすめ記事