痔になりやすい生活習慣とは?

題名のとおり、expectを用いた正規表現のgrepをしたいのですが、
以下のように記述し、入力し、実行すると

expect -c "

spawn ssh ~~~
expect \"password:\"
send \"hogehoge\n\"
expect \">\"
send \"zgrep "探したいもの" /なんかのログ.log.gz | grep -v "[0-9]%"\n\"
expect \">\"
send \"exit\n\"
"

以下のようにエラーが出てしまいます。

invalid command name "1-9"
while executing
"1-9"
invoked from within

[0-9]この部分を\[0-9\]このようにエスケープしてみても同じエラーが出てしまい、実行できません。
どのようにすれば正規表現として認識してくれるのでしょうか。

以上よろしくお願いいたします。

A 回答 (2件)

> "探したいもの" → \\\"探したいもの\\\"


> 上記の部分に関しましては、
> 最初にzgrepの部分でエスケープしているためか、エスケープせずとも問題ないようです。


ちょっと思い違いをしているようですが

まず、この expect -c " の"以降を解釈するのは、これを実行するシェルです。
このままだと

> send \"zgrep "

の後の"が、-c "の"に対応するクオートです文字列です。
「探したいもの」はクオート無しです。
\でエスケープした"は、他の文字と同じになり、それ自体にクオートする機能はありません。
「"send \"zgrep "探したいもの" /なんかのログ.log.gz | grep -v "[0-9]%"\n\""」
は、例えば
「"send Qzgrep "探したいもの" /なんかのログ.log.gz | grep -v "[0-9]%"\nQ"」
と書いたのと、文法的な解釈は同じなのです。

> send \"zgrep "探したいもの" /なんかのログ.log.gz | grep -v "[0-9]%"\n\"
は、
クオートを展開した文字列「 ... send "zgrep 」
直に書かれた文字列「探したいもの」
クオートを展開した文字列「 /なんかのログ.log.gz | grep -v 」
直に書かれた文字列「[0-9]%」
クオートを展開した文字列「\n" ... send "exit\n"」
となります。

直に書かれた文字列では、
・空白があったら、単語の区切りとなって、別の引数になる
・特殊な文字はファイル名展開対象とかで使われてしまう
ということになります。

この例では「探したいもの」と空白無しですが、実際はここに空白が入ったりしてませんか?
そして、そこで-cの引数としては切れてしまったりしていませんか?

あと、 \nじゃなくて\\nだと思います。

expect -c を echo にして、表示されるのが、期待通りのexpectスクリプトになっているかも確認してみてください。


こういうのは、
・変数展開とか必要が無いところはシングルクオートを使う
・ヒアドキュメントを使う
・別のファイルにする
のが間違いが少ないです。
    • good
    • 1

ダブルクォーテーションを二重にエスケープしないといけないのでは?



"探したいもの" → \\\"探したいもの\\\"
"[0-9]%" → \\\"[0-9]%\\\"

この回答への補足

回答ありがとうございます。

"探したいもの" → \\\"探したいもの\\\"

上記の部分に関しましては、
最初にzgrepの部分でエスケープしているためか、エスケープせずとも問題ないようです。
また、[0-9]の部分に関しましては二重でエスケープしてみましたが、同じエラーとなってしまいました。

send \"zgrep "探したいもの" /なんかのログ.log.gz | grep -v "[0-9]%"\n\"

以上よろしくお願いいたします。

補足日時:2011/04/05 15:15
    • good
    • 0

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

Q自動パスワード入力でscpするスクリプトでエラー「Unterminated quoted string」

Win2kのCygwinで下記のスクリプトを試してみました。

(ローカルのファイルをscpで自動転送)

$ uname -a
CYGWIN_NT-5.0 upsil 1.5.11(0.116/4/2) 2004-09-04 23:17 i686 unknown unknown Cygwin

$ cat ./test.sh
#!/bin/sh
HOST=192.168.1.105 # scp するマシン名を設定
UNAME=user01 # ログイン名を設定
PASSWD=xxxxxxxx # パスワ-ドを設定
TARGET=/cygdrive/c/cygwin/home/root/hoge
/usr/bin/zip -r $TARGET.lzh $TARGET
expect -c " # expect コマンドを実行
set timeout 20
spawn scp -P 60001 $TARGET.lzh $UNAME@$HOST:/home/fat32/ # expect コマンドの管理下でscpを実行する
expect login:\ ; send \"$UNAME\r\" # login: が出たらログイン名を打ち込む
expect sword:\ ; send \"$PASSWD\r\" # password: が出たらパスワ-ドを打ち込む
#expect \"$\" ; send \"ls\r\" # $ が出たら ls を打ち込む
#expect \"$\" ; send \"exit\r\" # $ が出たら exit を打ち込む

$ which expect
/usr/bin/expect

$ which zip
/usr/bin/zip

$ ./test.sh
と実行すると
: 9: Syntax error: Unterminated quoted string
となり、終ってしまいました。
「expect -c " # expect コマンドを実行」
が問題みたいなのですが何がまずかったのでしょうか?

Win2kのCygwinで下記のスクリプトを試してみました。

(ローカルのファイルをscpで自動転送)

$ uname -a
CYGWIN_NT-5.0 upsil 1.5.11(0.116/4/2) 2004-09-04 23:17 i686 unknown unknown Cygwin

$ cat ./test.sh
#!/bin/sh
HOST=192.168.1.105 # scp するマシン名を設定
UNAME=user01 # ログイン名を設定
PASSWD=xxxxxxxx # パスワ-ドを設定
TARGET=/cygdrive/c/cygwin/home/root/hoge
/usr/bin/zip -r $TARGET.lzh $TARGET
expect -c " # expect コマンドを実行
set timeout 20
spawn ...続きを読む

Aベストアンサー

おはようございます。
これはおそらく先の質問
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1115230
の参考URLを参照されたのだと思いますが、
私もそのままではうまくいきませんでした。
そのURLの例は間違っているのだと思います。
(動かした後でコメントをいれて、動作確認をしなかったのかな?)
ちなみにコメントを入れる場合は下のように、行末に;
をつけてから入れるとよいようです。

基本的にエラーの原因は#2さんのご指摘のとおりです。
参考URLも良く見ると最後に"がありますよ。(それでも動かないと思いますが。。。)
ただし、今の場合、最後に
interact
を入れないとうまく動かないとおもいます。(少なくとも私はそうでした。)
この掲示板の過去の質問が参考になりました。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=924035
http://oshiete1.goo.ne.jp/kotaeru.php3?q=925167

#!/bin/sh
HOST=192.168.1.105
UNAME=user01
PASSWD=xxxxxxxx
TARGET=/cygdrive/c/cygwin/home/root/hoge
/usr/bin/zip -r $TARGET.lzh $TARGET
expect -c "
set timeout 20
spawn scp -P 60001 $TARGET.lzh $UNAME@$HOST:/home/fat32/ ;こめんと
expect \"password:\" ;こめんと
send \"$PASSWD\r\" ;こめんと
interact
"

参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=924035
http://oshiete1.goo.ne.jp/kotaeru.php3?q=925167

おはようございます。
これはおそらく先の質問
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1115230
の参考URLを参照されたのだと思いますが、
私もそのままではうまくいきませんでした。
そのURLの例は間違っているのだと思います。
(動かした後でコメントをいれて、動作確認をしなかったのかな?)
ちなみにコメントを入れる場合は下のように、行末に;
をつけてから入れるとよいようです。

基本的にエラーの原因は#2さんのご指摘のとおりです。
参考URLも良く見ると最後に"がありますよ。(それでも動か...続きを読む

Qexpectの使い方について

expectの使い方についてご教示頂きたいことがあります。
内容は以下の通りです。

1)スイッチ機器にtelnetし、自動的に設定を行うようにしたい。
この機器の通常のプロンプトは"goo#"とする
"goo"はあらかじめ変数"host"として代入される。
telnet後、この装置のプロンプトが本当に goo#だったら"save"コマンドを実行する。

expect "${host}#"
send "save\n"

ここまではわかるのですが、ではgoo# 以外のプロンプトだったら即座に処理を中断
(別の処理)したいのです。


2)ログイン中に別ファイルを呼び出し、その中から1行ずつ抜き出して改行コードつきでコマンドを実行したい場合どうすればいいのか


http://www.linux.or.jp/JM/html/expect/man1/expect.1.html

このページは読んだのですが、いまいちよく理解できません。
よろしくお願いいたします。

Aベストアンサー

どもです。
参考にしてみてください。

#!/usr/local/bin/expect

set host "192.168.1.10"
set prompt "prompt"
set passwd "passwd"

set timeout -1
log_file expect.log
if [catch {open "./cmd.txt" r} fd] {
 puts "Can't open cmd.txt...\n"
 exit
}

spawn telnet $host
expect {
 "Connection timed out" {puts "\n\nTime out....\n"; exit}
 "password:"
}
send "$passwd\r"
expect {
 "Permission denied" {puts "\n\nPassword Invalid...\n"; exit}
 $prompt
}
while {[gets $fd line] >= 0} {
 send "$line\r"
 expect $prompt
}
send "exit\r"
expect eof
close $fd

どもです。
参考にしてみてください。

#!/usr/local/bin/expect

set host "192.168.1.10"
set prompt "prompt"
set passwd "passwd"

set timeout -1
log_file expect.log
if [catch {open "./cmd.txt" r} fd] {
 puts "Can't open cmd.txt...\n"
 exit
}

spawn telnet $host
expect {
 "Connection timed out" {puts "\n\nTime out....\n"; exit}
 "password:"
}
send "$passwd\r"
expect {
 "Permission denied" {puts "\n\nPassword Invalid...\n"; exit}
 $prompt
}
...続きを読む

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

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

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

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

Aベストアンサー

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

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

Qexpectを使って自動でSSHログインした後にコマンドを実行したいと

expectを使って自動でSSHログインした後にコマンドを実行したいと思っています。
df -hやmailqのようなコマンドは問題ないのですが、awkを利用してダラー?"$"を
入れてフィールド操作しようとするとダラーだけうまく読み込んでくれないのです。

■以下スクリプト
------------------------------------------------------------
read key
COMMAND="$key"
expect -c "
set timeout 3
spawn ssh アカウント@ドメイン
expect sword:
send パスワード\r
sleep 1
expect -re \"$\"
send \"${COMMAND}\r\"
expect logout: close
"
※クローズも正しくないみたいですが、無理やりtimeoutで閉じれているのでとりあえず。。

■実行結果
------------------------------------------------------------
spawn ssh アカウント@ドメイン
アカウント@ドメイン's password: can't read "NF": no such variable
while executing
"send "sudo awk '$NF>0' /proc/user_beancounters\r""

echoでCOMMANDを表示させるとちゃんと代入されているのです。
これがダラーを使わずに'{ptint}'とすれば問題ありません。となると
awkは問題ないので、やはり問題はダラーにあると思います。

バックスラッシュを入れてエスケープしてもダラーを二つ並べてもできません。
read "NFとなっているので、明示的に数字を入れてフィールドを指定してもだめです。


どなたかexpectのなかでダラーを読ませる方法をしりませんでしょうか。

expectを使って自動でSSHログインした後にコマンドを実行したいと思っています。
df -hやmailqのようなコマンドは問題ないのですが、awkを利用してダラー?"$"を
入れてフィールド操作しようとするとダラーだけうまく読み込んでくれないのです。

■以下スクリプト
------------------------------------------------------------
read key
COMMAND="$key"
expect -c "
set timeout 3
spawn ssh アカウント@ドメイン
expect sword:
...続きを読む

Aベストアンサー

$の前にバックスラッシュ2つ付けてください。
keyの入力で

ls -l | awk '{print \\$6}'

のようにします。

Qgrepで検索文字列が完全一致した行だけ取り出す方法

grepの文字列検索で検索文字列が単語として、完全一致した行だけ取り出す方法はないでしょうか?

通常は
grep hoge hoge.txt

と打つと、hogeが含まれる行が出力されますが、今回は含まれる行ではなくて完全に文字列が一致した行だけ取り出したいのです。

例えばhoge.txtの中に
cc ghoge
kkl hogem
jjll hoge
という3行があったとしたら最後の行でhogeという文字が空白で区切られた行だけ取り出したいのです。

何かよい方法があれば教えてください

Aベストアンサー

-w オプションじゃだめですか?

参考URL:http://www.linux.or.jp/JM/html/GNU_grep/man1/grep.1.html

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シェル 会話形式でエンターキーの動作は?

シェル内で、ENTERキーを押した時の動作をしたいと思います。
具体的には、もともと「telnetする、接続→ある値を入力する→ENTERを押す→入力した値に合わせたテキストが出力される→connection終了」という処理があり、
これを自動化して、出力されたテキストをファイルに保存するためのシェルを作りたいのです。

作ってみたところ、1点だけできないのがENTERキーを押す部分です。
シェルを実行すると、値の入力まで行われた状態で終わってしまいます。
そこで手動でENTERを押せば、正常に処理が終了します。

おそらく、会話形式でENTERを押した時の処理がうまくかけていないと思っています。
echo -e "\r\n"などいろいろ試したのですが・・・
echoではないのではないかと推測していますが、行き詰まりました。

どのようにしたらよいのかご教授ください。

Aベストアンサー

echo "
"

でいいんじゃないでしょうか。ちょっとやりたいことが正確には理解できていないかもしれませんが。
文法的にまちがって見えても、本当に改行してしまうところがミソです。

Qttlで戻り値を取得する方法

Teratermmacroでローカル(cygwin)に入り、サーバ(HP-UX)にリモートで入った後、
コマンドの戻り値で後の行動を操作したいのですが、うまくいきません。
わかる方、教えていただけませんか。

ざっくり以下のようなマクロを組んでいます。

----------------------------------------------------------
sendln 'ssh name@host1'

wait Prompt
sendln 'sendmsg "test"'(のようなコマンド) ←これの戻り値がほしい

if 戻り値 = 0 then
 ○○
elseif 戻り値 = 1 then
 wait Prompt
 sendln 'exit'
 wait Prompt
 sendln 'ssh name2@host2'

以下略
----------------------------------------------------------

上記の「戻り値」をどのようにすれば戻り値で判別してくれるでしょうか。
if文の条件式を $?やresultでやりましたが、どのような戻り値でも
必ず$?は0、resultは1で固定でした。

また、sendmsgとif文の間に以下のように試しましたが、失敗しました。
例1:
----------------------------------------------------------
sendln 'echo $?'
recvln

if inputstr = 0 then ←syntax errorになります。
 ○○
elseif inputstr = 1 then
----------------------------------------------------------

例2:http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1247390747参照
----------------------------------------------------------
sendln 'echo $?'
recvln
recvln

hensu=inputstr ←Type mismatch.のエラーになる。 直前にstr2intを入れたりしても駄目でした。
ちなみにsendln 'echo $?'を挟まずsendmsgの直後にrecvlnでも駄目です。

if hensu = 0 then
 ○○
elseif hensu = 1 then
----------------------------------------------------------

host1にシェルスクリプトを入れることは出来ません。

Teratermmacroでローカル(cygwin)に入り、サーバ(HP-UX)にリモートで入った後、
コマンドの戻り値で後の行動を操作したいのですが、うまくいきません。
わかる方、教えていただけませんか。

ざっくり以下のようなマクロを組んでいます。

----------------------------------------------------------
sendln 'ssh name@host1'

wait Prompt
sendln 'sendmsg "test"'(のようなコマンド) ←これの戻り値がほしい

if 戻り値 = 0 then
 ○○
elseif 戻り値 = 1 then
 wait Prompt
 sendln 'exit'
 wait Prompt
...続きを読む

Aベストアンサー

基本方針は、echo $? の出力文字をttlで受信して判定、でいいと思います。

・inputstrは文字列なので、=での比較はできません
strcompareコマンドで比較→変数resultで判定
あるいは
str2int 変数 intputstr で変数に数値化→if 変数=0 等と判定
ということになります。
http://ttssh2.sourceforge.jp/manual/ja/macro/syntax/variables.html
http://ttssh2.sourceforge.jp/manual/ja/macro/command/strcompare.html
http://ttssh2.sourceforge.jp/manual/ja/macro/command/str2int.html


・recvln1つではエコーバックの分を受け取ってしまうようです。
他の出力を受信してしまう場合もあります。
確実にやるなら、目印を付けてwaitでそこまで待つ、というのがいい思います

sendln 'echo "=== EXIT STATUS === : $?"'
wait '=== EXIT STATUS === : '
recvln


・シェルスクリプトを入れることはできなくても、複合コマンドを実行することはできるはずです。
sendln '(sendmsg "test" && echo "==== OK ====") || echo "==== NG ===="'
waitlnで待ち→resultで分岐とできます
http://ttssh2.sourceforge.jp/manual/ja/macro/command/waitln.html

基本方針は、echo $? の出力文字をttlで受信して判定、でいいと思います。

・inputstrは文字列なので、=での比較はできません
strcompareコマンドで比較→変数resultで判定
あるいは
str2int 変数 intputstr で変数に数値化→if 変数=0 等と判定
ということになります。
http://ttssh2.sourceforge.jp/manual/ja/macro/syntax/variables.html
http://ttssh2.sourceforge.jp/manual/ja/macro/command/strcompare.html
http://ttssh2.sourceforge.jp/manual/ja/macro/command/str2int.html


・recvln1つではエコーバ...続きを読む

Qscpコマンドでリモートサーバのファイルを削除したい

winscpでリモートサーバのファイル削除が出来るので、てっきりscpコマンドでオプションがあるのかと思ったのですが、見当たりません。scpコマンドでリモートファイルの削除は可能でしょうか?誰か教えて!

Aベストアンサー

1番の方と同じ意見ですが、
ssh ホスト名 コマンド
でリモートサーバ上でコマンドが実行できますので

ssh SSH_SERVER "rm testfile"

のように実行するの一般的かと。

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/の数字部分が日本語です。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング