質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

Q&A

解決済

2回答

12990閲覧

$(...)で空白を含む出力を適切に引数にしたい

Eki

総合スコア429

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

0グッド

0クリップ

投稿2016/10/23 12:08

実現したいこと

たとえば ./command.sh prefix:arg1 prefix:arg2 という形式をとる command.sh があるとして、
その中で ./another_command.sh arg1 arg2 というように引数からそのまま prefix: を除いたものを引数にとるコマンドを実行したいとします。
このときに引数から prefix: を消したものを表示する別のスクリプトを用意して

prefix_eraser.sh:

sh

1#!/bin/bash 2modified=() 3 4for arg in "$@"; do 5 arg=$(echo "$arg" | sed -e 's;^prefix:;;') 6 modified+=("$arg") 7done 8 9echo "${modified[@]}"

使うときには command.sh で ./another_command.sh $(./prefix_eraser.sh "$@") とかすればいいのでは、と思ったのですが、もともとの引数に空白が含まれていると、 another_command.sh に渡るときには分割されて渡されてしまいます。
たとえば具体的に command.sh と another_command.sh を

command.sh

sh

1#!/bin/bash 2 3./another_command.sh $(./prefix_eraser.sh "$@")

another_command.sh

sh

1#!/bin/bash 2 3for arg in "$@"; do 4 echo $arg 5done

のようにすると、

sh

1$ ./another_command.sh prefix:a prefix:b\ c prefix:c 2prefix:a 3prefix:b c 4prefix:c 5 6$ ./command.sh prefix:a prefix:b\ c prefix:c 7a 8b 9c 10c

command.sh 内の $(./prefix_eraser.sh "$@") が展開されるときには '\ ' もただの空白になっているのが原因だと思いますが、この「一つの引数の区切り」情報を維持したまま渡すことはできないのでしょうか?
長くなりましたが、どうかよろしくお願いします。

試したこと

prefix_eraser.sh で echo "${modified[@]}" のようには出力せず for で回しながら一つずつ改行区切りで出力させて another_command.sh の中で IFS を改行だけにしてから新しい配列を用意し for で回しながら配列に追加、また "${modified[@]}"のようにして文字列化する、という方法ならば区切りを保持できましたが、いかんせん面倒なのでサクっとできる方法はないのかと思った次第です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

'で囲んで、evalします。
また、for arg in "$@"は、普通はfor argと書きます。

Bash

1:::::::::::::: 2another_command.sh 3:::::::::::::: 4#!/bin/bash 5 6for arg; do 7 echo $arg 8done 9:::::::::::::: 10command.sh 11:::::::::::::: 12#!/bin/bash 13 14eval ./another_command.sh $(./prefix_eraser.sh "$@") 15:::::::::::::: 16prefix_eraser.sh 17:::::::::::::: 18#!/bin/bash 19modified=() 20 21for arg; do 22 arg=$(echo "$arg" | sed -e 's;^prefix:;;') 23 modified+=("'$arg'") 24done 25echo "${modified[@]}"

また、この例であれば、prefix_erase.shを作らず、command.shでパラメーターの置換を使って、こう書けます。

Bash

1:::::::::::::: 2command.sh 3:::::::::::::: 4#!/bin/bash 5 6./another_command.sh "${@/#prefix:/}"

投稿2016/10/23 12:54

otn

総合スコア84557

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Eki

2016/10/23 13:12

ありがとうございます、まさにこういうことを求めていました。 試してみたところすっきり解決しました。 また for arg; とできることは知りませんでした、便利なので使っていこうと思います。 パラメータの置換もとてもスマートですね。また調べてみます。
guest

0

prefix_eraer.shの必要性がちょっと分からなかったので、command.shで直接another_command.shを呼び出すようにしてみました。

#!/bin/bash modified=() for arg in "$@"; do arg=$(echo "$arg" | sed -e 's;^prefix:;;') arg="$arg" modified+=("$arg") done ./another_command.sh "${modified[@]}"

another_command.shに引数を渡すときに、個々の引数をダブルクォーテーションで囲った状態で渡せば希望する通りの動きになります。

投稿2016/10/23 12:45

編集2016/10/23 12:47
ynakano

総合スコア1894

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Eki

2016/10/23 12:52

回答、ありがとうございます。 この例では単純化したのですが、実際の prefix_eraser.sh はもうちょっと長いのと、ほかのシェルスクリプトからも利用したいようなものなので、できれば別ファイルに分けておきたいのです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問