スクリプトに引数として渡されると、シェルスクリプトの出力が誤って分割されます。

スクリプトに引数として渡されると、シェルスクリプトの出力が誤って分割されます。

次の2つのシェルスクリプトがあるとします。

#!/bin/sh
#This script is named: args.sh

echo 1 "\"Two words\"" 3

、そして:

#!/bin/sh
#This script is named: test.sh

echo "Argument 1: "$1
echo "Argument 2: "$2
echo "Argument 3: "$3

スクリプトを呼び出すとき:

sh test.sh $(sh args.sh)

、私は受け取った:

Argument 1: 1
Argument 2: "Two
Argument 3: words"

私が得ると予想される場合:

Argument 1: 1
Argument 2: Two words
Argument 3: 3

出力をコピーしてsh args.sh入力として貼り付けるのはうまくいくsh test.shので、実際にシェルが行うことではないと思います。を呼び出すことで、目的の/予想される出力を得ることができますsh args.sh | xargs sh test.sh

しかし、最初のスクリプト(args.sh)の出力をxargsにパイピングせずにこれを行うための同等の方法があるかどうか疑問に思います。スクリプトを元の順序で呼び出したい。パラメータスクリプトは、パラメータを2番目のスクリプトとして出力します。また、この呼び出しが期待どおりに機能しない理由の説明を探しています。

ベストアンサー1

問題の一部は、args.shから返された文字列が直接コマンドのように解析されず、$' \t\n'$ IFS()の値によってのみ解析されることです。以下を使用してコマンドトレースをオンにしますset -x

$ sh /tmp/test.sh $(sh /tmp/args.sh)
++ sh /tmp/args.sh
+ sh /tmp/test.sh 1 '"Two' 'words"' 3
Argument 1: 1
Argument 2: "Two
Argument 3: words"
$

Singleで始まる行に注意してください+。 4つの引数があり、そのうちの'"Two'2'words"'つは別々の引数として解析されます。あなたが望むのは$ IFSを変更することです。

$ set -x
$ IFS='"'
+ IFS='"'
$ sh /tmp/test.sh $(sh /tmp/args.sh)
++ sh /tmp/args.sh
+ sh /tmp/test.sh '1 ' 'Two words' ' 3'
Argument 1: 1
Argument 2: Two words
Argument 3:  3
$

これはすべての出力に適用されるわけではありません。最善の方法は、args.shの出力を変更して、出力をスペース以外のカンマやコロンなどの文字で区切ることです。

$ cat /tmp/args.sh
#!/bin/sh
#This script is named: args.sh

echo "1,Two words,3"
$ IFS=,
$ sh /tmp/test.sh $(sh /tmp/args.sh)
+ sh /tmp/args.sh
+ sh /tmp/test.sh 1 Two words 3
Argument 1: 1
Argument 2: Two words
Argument 3: 3
$

おすすめ記事