あなたの映画力を試せる!POPLETA映画検定(無料) >>

bashのスクリプトで質問です。

hoge_command 何らかのコマンド
bashtest.sh bashスクリプト

とあるときに、

hoge_command | bashtest.sh

のようにパイプでの入力をスクリプト内で受け取る方法はありますか?

たとえばperlであれば、

while(<STDIN>){
....

のようにして受け取ることができると思いますが、
bashでは、どのようにすればよいでしょう。

また、bashtest.sh で、引数無しのときにUsageを出すようにしてあった場合にうまく動作しないので、

hoge_command | bashtest.sh -

のように記述して受け取る方法はあるでしょうか?

(同じくperlなら、
if( $ARGV[0] eq "-" ){
while(<STDIN>){
....

のように書いて逃げるところと思います。

初歩的なことで恐縮ですが、よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (4件)

>この場合、次のような方法でよいでしょうか。


>他に良い方法があれば、あらためて教えてください。

これでよいと思います。
あと、commandx a b c と commandx "a b c" とはcommandxの動作は同じですか?もし違うなら、最後の commandx "$c" は、 commandx $c と " " をつけないのが正解です。引数の個数が3個か、1個かの違いがあります。
    • good
    • 0
この回答へのお礼

notnotさん、何度もご回答ありがとうございました。

>もし違うなら、最後の commandx "$c" は、 commandx $c と " " をつけないのが正解です。
>引数の個数が3個か、1個かの違いがあります。

あ、なるほど! 大変勉強になりました。
これで一通りのことがすっきり出来ました。
ありがとうございました。

お礼日時:2005/07/19 09:28

#2です。


下記の方が良いと思います。
bashtest.sh abc - def ghi
のような途中に - があるケースにも対応できる。

for arg
do
case "$arg" in
-)
while read a; do
commandx "$a"
done
;;
*)
commandx "$arg"
;;
esac
done

この回答への補足

notnotさん、何度もありがとうございます。
for argで回す方法について理解しました。

もともとやりたかったことに対して、正確には次のようにしたかったのですが、

%bashtest.sh a b c

とやっても、

%echo a b c | bashtest.c -

とやっても、
(あるいは、%echo c | bashtest.sh a b - とやっても?)

bashtest.shの中では、

commandx a b c

のように呼び出すようにさせる。

この場合、次のような方法でよいでしょうか。
他に良い方法があれば、あらためて教えてください。


c=""

for arg
do
case "$arg" in
-)
while read a; do
c="$c $a"
done
;;
*)
c="$c $arg"
;;
esac
done

commandx "$c"

補足日時:2005/07/15 15:37
    • good
    • 0

・引数なしなら usage を出す


・引数があれば入力ファイルと見なしてそのファイルから読む
・引数が - なら標準入力から読む
だとすると、cat の機能を使って、

if test "$*" = ""
then echo Usage: aaaaaa bbbbb cccc
  exit 0
fi
cat "$@" |
while read a
do 読んだデータ "$a" を使う処理
done
    • good
    • 0
この回答へのお礼

ご丁寧なご回答ありがとうございました。
私の質問が曖昧だったようで、すみません。
引数やパイプで受け取るのはファイル名ではなく文字列そのものとしたかったのです。
教えていただいた方法とミックスして、結果的には次のように書きました。

if test $# -eq 0
then
echo "Usage: $0 {strings|-}"
exit
fi

case "$1" in
-)
while read a; do
commandx "$a"
done
;;
*)
for a in "$@"; do
commandx "$a"
done
;;
esac

とりあえず、やりたかったことは出来るようになりました。
ありがとうございました。

お礼日時:2005/07/13 16:22

bash自身の機能として、標準入力を取得するみたいな機能は、無かったはずです。



こういった場合、スクリプト内で、入力を最初に受け取るコマンドに対してリダイレクトするような意味合いの書き方になるはずです。
汎用的な書き方としては、readコマンドを使ったこんなやり方があります。

$ cat test2.sh
#!/bin/sh

while read line
do
echo $line
done

$ echo hogehoge | bash test2.sh
hogehoge

awkでもsedでも、入力を指定しなければ勝手に標準入力から取ろうとするので、何でもいけるはずですよ。
また、初期化処理の段階で引数処理も可能なので、引数にファイル名があったら、入力をそこからとり、無ければ標準入力を待ち受けるといった処理も可能でしょう。
    • good
    • 0
この回答へのお礼

引数無しで、Usageを出すということをしたかったため、複雑にしてしまいました。

while read の構文について、参考にさせて頂きました。

ご丁寧なご回答ありがとうございました。

お礼日時:2005/07/13 16:24

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qbashで変数にパイプを入れ、コマンドとして使う?

パイプを含む文字列が入った変数をシェルコマンドとして実行する方法がありましたら
教えてください。

Linux環境で、bashを使って定期的にモニタリングするスクリプトを書こうとしています。
スクリプトの引数で実行するモニタリングコマンドを変えれるようにしたいのですが、
パイプが入っているとうまくいきません。

下記のようなスクリプトで、引数に "ps -ef | grep pty" と入れたら、定期的に
そのようなコマンドを実行できるようにできますでしょうか?
(引数指定時に、きちんとクォーテーションで全体を囲んで、パイプが評価されない
ようにしてもダメでした。)

変数として入ったコマンドを実行するときに、パイプがシングルクォーテーションで
囲まれて "ps -ef '|' grep pty" のようになってしまい、パイプとして実行時に認識
されないようです。

bashシェルで設けてる制約でしょうか?回避策などありますでしょうか?


<<スクリプト poll.sh>>
##
# Defs
export RUNCMD='finger'
export INTERVAL=10

##
# Getopt
while getopts "t:" OPT; do
case ${OPT} in
t) INTERVAL=${OPTARG};;
esac
done
shift $((OPTIND-1))
[ ${#} -gt 0 ] && RUNCMD="${*}"

##
# Main part

while :; do (set -x; ${RUNCMD}; sleep ${INTERVAL}); done

パイプを含む文字列が入った変数をシェルコマンドとして実行する方法がありましたら
教えてください。

Linux環境で、bashを使って定期的にモニタリングするスクリプトを書こうとしています。
スクリプトの引数で実行するモニタリングコマンドを変えれるようにしたいのですが、
パイプが入っているとうまくいきません。

下記のようなスクリプトで、引数に "ps -ef | grep pty" と入れたら、定期的に
そのようなコマンドを実行できるようにできますでしょうか?
(引数指定時に、きちんとクォーテーションで全体を...続きを読む

Aベストアンサー

while :; do (set -x; eval "${RUNCMD}"; sleep ${INTERVAL}); done

evalは引数の内容をコマンドとみなして実行する組み込みコマンドです。
evalが実行された時点でダブルクォーテーションで括られたシェル変数が展開されるため、
RUNCMD='ps -ef | grep pty'なら、実際に実行されるコマンドは

ps -ef | grep pty

となり、期待通りの動作をするのではないでしょうか?

$ set -x
$ RUNCMD='ps -ef | grep pty'
+ RUNCMD='ps -ef | grep pty'
$ eval "$RUNCMD"
+ eval 'ps -ef | grep pty'
++ grep pty
++ ps -ef
test   32706 32559 0 10:12 pts/2  00:00:00 grep pty

Qbashなどのシェル変数の値に改行を含める事は可能でしょうか?

タイトルの通りですが、通常のシェル変数の値として

 [prompt]$ aaa="bbb<改行>ccc"

のようなセットを行い、

 [prompt]$ echo $aaa
 bbb
 ccc
 [prompt]$

のような結果を得たいのですが、可能でしょうか。

Aベストアンサー

可能です.
というか,やってみたら出来ることがわかると思います.こんなところで聞くより早い.
なお,sh/bash系では改行文字は特にエスケープせずそのまま入れられます.

aaa='bbb
ccc'

Qsedの置換文字に変数を使用したいのですが・・・

あるファイルの特定の文字を変換し、上書きをする処理を行いたいのですが、sedの置換文字に変数が渡せなくて困っています。

例:
X="a"
Y="b"
echo test.txt | sed 's/${X}/${Y/g}' >test.txt

sedでは置換文字に${X}といった変数を使用することはできないのでしょうか?

Aベストアンサー

' ・・・' で囲まれた中の$はそのままドルマークです。変数展開をするなら、'・・・'で囲んではいけません。

何も囲まないか、"・・・"で囲むかです。

Qshellスクリプトから別のshellスクリプトを呼び出す方法

今現在VineLinux4.1をサーバとして起動させております。
その関係もありまして維持としてシェルを動かす事はある意味必須の状態です。
本題はAと言うスクリプトからBと言うスクリプトを呼び出す方法がわかりません。
試してみた方法はsourceで呼び出す方法です。
A.shの中身を以下とすると

#!bin/bash
echo ="B.shを呼び出します"
source B.sh
echo ="シェルスクリプトを終了します"
exit 0

上記のようにした場合、最初のecho文は出力され、B.shの内容を一通り終えると最後のechoは出力されずA.shは完了しません。
ごくごく基本的なことかもしれませんが、うまく検索にも引っ掛けられなかったので、ご質問させていただきます。
よろしくお願い致します。

Aベストアンサー

#2です。

>cshは=の前後にスペースが入るかと思いますが、今回はbashを指定しておりますので。

cshの何のことを言ってるのかわかりませんが、例えばbashで、
echo="シェルスクリプトを終了します"
は、echoコマンドじゃなくて、echo というシェル変数に「シェルスクリプトを終了します」という文字列をセットするコマンドになります。当然何も表示されません。

>A.shとB.shは単独で正常に稼動できる状態です。

B.shが単独で正常に動いているように思えることは、B.shに問題がないことを意味しません。
例えば、B.sh をexitで終了したりするとそこでbashは終了するわけだし。

>質問の例はあくまで例ですが、

書かれているA.shに問題がなさそうなので、B.shの中に原因があると想像しました。
現象が発生する最小限の、A.sh と B.sh の内容をすべて正確に書いてください。

今気づきましたが、A.sh の最後に無意味なexit 0がありますが、もしかして、B.shの最後にもexit 0が?

source コマンドは、その場所に指定したファイルの内容を挿入するコマンドです( C の #include 相当 )。もし、新たにbashプロセスを起動して、そこでB.shを動かしたいなら、
bash B.sh
です。他には#1の方が書いた方法もあります。

#2です。

>cshは=の前後にスペースが入るかと思いますが、今回はbashを指定しておりますので。

cshの何のことを言ってるのかわかりませんが、例えばbashで、
echo="シェルスクリプトを終了します"
は、echoコマンドじゃなくて、echo というシェル変数に「シェルスクリプトを終了します」という文字列をセットするコマンドになります。当然何も表示されません。

>A.shとB.shは単独で正常に稼動できる状態です。

B.shが単独で正常に動いているように思えることは、B.shに問題がないことを意味しませ...続きを読む

Qシェルスクリプトでファイル内の数値文字列を数値として扱うには

失礼します。
シェルスクリプトでファイル内のテキスト(数値文字列)を取得して、それを使って計算するにはどうすれば良いでしょうか?

str:ファイル内のテキスト(数値文字列)

res=$(( $str + 1 ))

・エラー
")syntax error: invalid arithmetic operator (error token is "


よろしくお願いします。

Aベストアンサー

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをexprに書き換えたところ
$ ./test2.sh
Using expr
09:19:00.302748000
09:19:19.259990000

exprだと19秒ですが、$(( 演算 )) だと10秒程度なので、演算が多くなれば確かにexprは不利ですね。

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをe...続きを読む

Qsedなどで、特定の文字列の後の文字列を抽出したい

sedなどで、特定の文字列の後の文字列を抽出したい

シェルスクリプト内で、sedなどを使って特定の文字列の後の文字列を抽出したいのですが、どうすればいいでしょうか?

たとえば、abcXYZ123defghiのなかから、XYZの後の「123」を抜き出したいです。

echo abcXYZ123defghi | sed ...

のようにして実行させたいです。

Aベストアンサー

日本語対応sedだと日本語数字混じりでもできますね。

echo abcXYZ12357defghi | sed -e 's/^.*XYZ\([0-90-9]*\).*$/\1/' -e 'y/0123456789/0123456789/'
12357

※ 使っている日本語コードの指定は必要かも(例えば、 --ctype=EUC)

echo abcXYZ12357defghi | sed -e 's/^.*XYZ\([0-90-9]*\).*$/\1/'
12357

※ 入力フォームに書いている時はASCIIと日本語の判別がし易いけど回答見るとわかり難いですね。後ろの例での結果57とy/0123456789/の数字部分が日本語です。

Qvlookup関数で検索値を含む文字列を検索する方法

vlookup関数で例えば E1のセルに=vlookup(D1,A:C,3,false)とした場合、D1が佐藤であれば、A列に「佐藤」がある場合には当然、「佐藤」がある行の3列目の値が返されますが、「佐藤」はなく「佐藤A」や「A佐藤」がある場合にもこれらがある行の値を返して欲しいのですが、いい方法はありませんでしょうか。*を使ってできると思ったのですがうまくいきません。上記例で、=vlookup("*佐藤*",A:C,3,false)とすればできますが、*佐藤*の部分はD1の引用を利用したいのです。
 よろしくお願いします。

Aベストアンサー

=VLOOKUP("*"&D1&"*",A:C,3,FALSE)

Qpingでポートの指定

pingでIPアドレスを指定して、通信できるかどうかというのは
よく使いますが、pingでポートを指定して応答するかどうかは調べられるのでしょうか?

よろしくお願いします

Aベストアンサー

pingを含むICMPというプロトコルは、OSIの7レイヤで言うところのL2(同一セグメント内通信)とL3(IPルーティングされた通信)の両方にまたがる、ちょっと珍しいプロトコルです。

IPアドレスは指定できますが、別サブネットに属するIPアドレスに到達できればL3通信、できなければゲートウェイと呼ばれる同一サブネットに属する中継装置からの回答を得るという点でL2(MAC通信ではなく、同一セグメント内通信という意味)通信です。

ポート番号はL4で使用されるアドレスですから、L4機能の疎通確認はping(を含むICMP)ではできません。

FTPの疎通確認であれば、クライアントからサーバに対するTCP/21通信(FTP-CMD)が可能であること(サーバからクライアントへのTCP/21からの応答を含む)+サーバからクライアントに対するTCP/20通信(FTP-DATA)が可能であること(クライアントからサーバへのTCP/21からの応答を含む)が必要でしょう。

監視ソフトによるものであれば、
・クライアントからサーバへのログイン(TCP/21)
・クライアントからサーバへのlsの結果(TCP/20)
で確認すればよいでしょう。

pingを含むICMPというプロトコルは、OSIの7レイヤで言うところのL2(同一セグメント内通信)とL3(IPルーティングされた通信)の両方にまたがる、ちょっと珍しいプロトコルです。

IPアドレスは指定できますが、別サブネットに属するIPアドレスに到達できればL3通信、できなければゲートウェイと呼ばれる同一サブネットに属する中継装置からの回答を得るという点でL2(MAC通信ではなく、同一セグメント内通信という意味)通信です。

ポート番号はL4で使用されるアドレスですから、L4機能の疎通確認はping(を含む...続きを読む

Q「いずれか」と「いづれか」どっちが正しい!?

教えて下さいっ!
”どちらか”と言う意味の「いずれか」のかな表記として
「いずれか」と「いづれか」のどちらが正しいのでしょう???

私は「いずれか」だと思うんですが、辞書に「いずれか・いづ--。」と書いてあり、???になってしまいました。
どちらでもいいってことでしょうか?

Aベストアンサー

「いずれか」が正しいです.
「いづれ」は「いずれ」の歴史的かな遣いですので,昔は「いづれ」が使われていましたが,現代では「いずれ」で統一することになっていますので,「いずれ」が正しいです.

QVB上で実行中の無限ループの止め方

今まで、CUIベースのBASICでのプログラムの経験はあるのですが
Visual系のBASICは初心者です。
原因はわかっているのでプログラムの修正はできるのですが
VB上でコンパイルして実行したときに無限ループに陥ってしまって
どうにもプログラムをとめられなくなります。
そんなことがないように、実行前に全てのプロジェクトを保存して
いますので、そんなに実害はないのですが、どうすればとめられるのでしょう・・
今現在は、タスクマネージャーから強制終了させています。

Aベストアンサー

無限ループの一番内側に
DoEvents
を入れておくと、ウィンドウ切替え->デバッガ終了操作が出来ますよ

危なそうなとこにも入れておくと、何かと安心です。


人気Q&Aランキング