入れ子になったシェルスクリプトはリスト変数では機能しません。

入れ子になったシェルスクリプトはリスト変数では機能しません。

次の2つの最小シェルスクリプトを作成しました。

テスト1

#!/usr/bin/env bash

letterList=$1

for letter in $letterList
do
    echo $letter
done

そして第二

テスト2

#!/usr/bin/env bash

letterList=$1

test1 $letterList

実行すると、目的の出力をtest1 'A B C'取得しAます。BC

ただし、実行すると発生するとtest2 'A B C'予想されますが、test1 'A B C'実際の出力はA

したがって、入れ子になった変数のリストが読み込まれない、つまり実行されているように見えますtest1 A

何が起こっているのか、どのようにして欲しい結果が得られますか?

PS:関連する場合は、OS Xを使用しています。

答え1

コードにリスト変数がありません。あなたはロープを持っています。

test1引用符なしで拡張を使用する呼び出しです$letterList。これにより、シェルはその値をスペース、タブ、および改行(デフォルト)から複数の単語に分割し、各単語にファイル名ワイルドカードが含まれている場合はファイル名ワイルドカードになります。結果の単語はtest1別の引数として渡されます。

では、test1これらのパラメータの最初のものをに入れますletterList

$letterList文字列をtest1from as isに渡すには、test2呼び出し時に拡張子を二重引用符で囲む必要があります。

test1 "$letterList"

しかし、あなたは頼る$letterListループの値の分割はシェルで行われますがtest1(問題を引き起こすのと同じメカニズム)、コードが誤ってファイル名のグロービングを実行するのを防ぐことはできません(たとえば、スクリプトをテストして何を意味するのtest2 "A B C *"かを確認)。


合格したい場合リスト単一の文字列ではなくtest2文字列の代わりにリストを使用して呼び出します。

test2 A B C "Hello World" "* *"

次に、test2パラメータを次に渡しますtest1

#!/bin/sh

test1 "$@"

ここでは、"$@"位置引数(スクリプトのパラメータ)のリストが展開され、個々の引数が参照されます。これは、このようなパラメータがHello World呼び出し時に複数のパラメータに分割されず、test1文字列が* *2つに分割されず、ファイル名の一致が発生しないことを意味します。

test1パラメータを繰り返します。

#!/bin/sh

for arg in "$@"; do
    printf '%s\n' "$arg"
done

または

#!/bin/sh

for arg do
    printf '%s\n' "$arg"
done

...またはパラメータのみを印刷したい場合

#!/bin/sh

printf '%s\n' "$@"

/bin/shこれには特定の項目がないため、全体的にシェルとして使用していますbash

答え2

./test2 'a b c'実行すると、次のようになります。

$1=a b c

したがって、最後の行は次のようになります。

test1 a b c

実行すると、test1次のようになります。

$1=a
$2=b
$3=c

つまり、指定されたパラメータはtest1引用符で囲まれていないため、1つではなく3つのパラメータになります。

test1単一のパラメータを渡すには、変数を二重引用符で囲みます。つまり、最後の行を次のようtest2に置き換えます。

./test1 "$letterlist"

../.$PATH

答え3

実際の目標が何であるかは不明です。あなたが明確に言う唯一のことは、3つの別々の行とtest2 'A B C' 出力をしたいということですABC

そのような結果を提供できる他の解決策があります。通常、出力は次のように見えます。 ケルムの答え

  • test2同じままにしてください。
  • test1次のように変更します。

    #!/bin/sh
    
    for letter in $*
    do
        printf '%s\n' "$letter"
    done
    

    そうすれば、自然に行動が変わりますtest1。今$1。したがって、、、および(単に、および代わりに)がtest1 'A B C' 'D E F'6つの別々のラインに出力されます。ABCDEFABC

$*スペースを含む文字列を別の単語に分割するため、通常は使用をお勧めしません。たとえば、2つの"lazy dog"単語(パラメータ)になります。しかし、これはまさにあなたが望む行動のようです。

printfechoファイル名の先頭より少し安全です。-または含まれています\。このサイトではすでにこれについて詳しく説明しています。もっと知りたい場合は、検索してみてください。

関連情報