こんにちは。
シェルスクリプトで謎の現象が起こりまして悩んでいます。

現在、
#!/usr/bin/sh
var='foo'
if [ $? - eq - 0 ]; then
mv xxx.bz2 xxx.old.bz2
echo $var | bzip2 -z >xxx.bz2
fi
といった感じのシェルスクリプトを動かしています。
これを手作業で、
foo | bzip2 -z >xxx.tmp.bz2
とやると、xxx.tmp.bz2は1.2MB程度のファイルとなるのですが、
上記のシェルスクリプトで実行すると8KBほどにしかなりません。

シェルスクリプトの変数のサイズの制限かと思い、調べてみましたが、
特に制限があるとの資料はみつかりませんでした。
fooの出力がバイナリなので、そのせいかとも思ったのですが、unix系列の場合、windowsと違ってテキスト/バイナリの区別はないはずだしということで、理由がわかりません。

シェルの変数には、やはり制限があるのでしょうか?それとも他の理由でしょうか。ご存知の方がいらっしゃいましたら、ご教示お願いします。

環境はsolarisです。バージョンは、
$ cat /etc/release
Solaris 10 8/07 s10s_u4wos_12b SPARC
Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
Use is subject to license terms.
Assembled 16 August 2007

です。よろしくお願いします。

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

A 回答 (4件)

変数と言うより、シェルのコマンドライン長の制約の気がします。


圧縮して1.2MBということはfooの出力は数十~数百MB?
外部コマンド起動の場合は、Linuxだと128KBが上限のようですが、echoは組み込みコマンドなので、もっと上限は大きいはずです。
変数に200MBいれてみると、入りましたけど、echoしてみるとbashが落ちました。SolarisだとOSが違うので、上限も異なると思いますが。

やはり変数に入れない方がいいでしょうね。

foo | bzip2 -z >xxx.tmp.bz2
ただ、ステータスを調べるのは面倒。パイプのステータスはパイプの最終段のコマンドつまりbzip2のステータスになります。

bashだと、${PIPESTATUS[0]} でfooのステータスが取れるのですが、shだとちょっと細工が要ります。

status=`((foo ; echo $? >&3) | bzip2 -z >xxx.tmp.bz2) 3>&1`
if [ $status = 0 ]
then mv xxx.bz2 xxx.old.bz2; mv xxx.tmp.bz2 xxx.bz2
else rm xxx.tmp.bz2
fi

この回答への補足

うまくいきました。ありがとうございます。

補足日時:2009/05/15 14:07
    • good
    • 0
この回答へのお礼

なるほど、ありがとうございます。
どうやら変数に入れないほうがいいのは確かなようですね。

>ただ、ステータスを調べるのは面倒。パイプのステータスはパイプの最終段のコマンドつまりbzip2のステータスになります。
はい、ステータスを調べる必要があるので・・。必要なければ素直に
foo | bzip2 -z >xxx.tmp.bz2
で、よかったのですが。
>status=`((foo ; echo $? >&3) | bzip2 -z >xxx.tmp.bz2) 3>&1`
>if [ $status = 0 ]
>then mv xxx.bz2 xxx.old.bz2; mv xxx.tmp.bz2 xxx.bz2
>else rm xxx.tmp.bz2
>fi
参考になります。試してみます。

お礼日時:2009/05/15 10:08

んー。

fooの出力結果をbz2で保存したいというのが目的でよいのかな?

Solaris は、時々コマンドが微妙に違っていたりするのであまり自信ないですけど
シェルでは、基本的にクォーティングする癖をつけた方がよいですよ。

#!/usr/bin/sh
var="$(foo)"
if [ $? -eq 0 ]; then
mv xxx.bz2 xxx.old.bz2
echo "$var" | bzip2 -zc >xxx.bz2 || echo error
fi

としてみたら、どんなです?
もしうまくいったとしたら、$varに0x0dが混ざっていたのでしょう。
    • good
    • 0
この回答へのお礼

お返事ありがとうございます。
テストコードを書いてみました。
$ cat test.sh
#!/usr/bin/sh
var0="\0015"
var=12345${var0}A
echo $var
echo "$var"

$ test.sh
A2345
A2345

と、なりましたので、どうやら改行が原因ではないようです。
他、
var0="\0042"
としても試してみましたが、結果、
12345"A
12345"A
と、なりましたので、バイナリであることはおそらく問題がないのかなと思います。
いずれにせよ、あまり大きなデータを変数に入れるのは問題があるようなので、変数に入れない方向で考えてみます。

お礼日時:2009/05/15 11:19

echo は文字列しか処理できないんじゃない?


シェルにも
echo $var | bzip2 -z >xxx.bz2
じゃなくて
foo | bzip2 -z >xxx.tmp.bz2
って書けばどう?
    • good
    • 1

この場合


echo $var = echo foo
だから, 「コマンド foo の出力を bzip2 で圧縮する」んじゃなくて「文字列 foo を bzip2 で圧縮してる」んだよ.

この回答への補足

すみません、間違えました。
var='foo'
じゃなくて、
var=`foo`
でした。申し訳ないです。

補足日時:2009/05/14 19:10
    • good
    • 0
この回答へのお礼

重ねてすみません。
間違えたというのは、転記ミスということです。
うまく動かないスクリプトに書いてあるのは、
var=`foo`
です。

お礼日時:2009/05/14 19:15

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

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

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

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

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

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

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

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

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

Aベストアンサー

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

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

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...続きを読む

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

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

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

のようなセットを行い、

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

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

Aベストアンサー

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

aaa='bbb
ccc'

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

Q空白を含んだシェル変数の代入

こんにちは。
空白を含んだシェル変数の代入について教えてください。

set test1="ABCD EFGHIJ"
set w1=$test1
echo "w1 = $w1"

このようなシェルスクリプトを実行させた時
w1 = ABCD
と表示されてしまいます。
解決案があれば教えてください。

よろしくお願いします。

Aベストアンサー

set w1="$test1"

ダブルクォーテーションで囲ってください。
この場合シングルはダメです(変数内容が展開されません)。

Qcsh (tcsh)での環境変数の長さの制限について教えて下さい。

Solaris8 (SPARC)上でJavaでいろいろ開発をしているのですが、
シェルの環境変数の長さに制限があるようで困っています。
具体的には、あちこちに散在しているjarファイルを参照する必要
があるので、環境変数 $CLASSPATHが非常に長くなっていて、
現在の設定以上に CLASSPATHを追加しようとすると「Word too long」
というエラーが出て設定できません。
1つの環境変数の長さの制限を変更することは可能でしょうか?
もしくはなにか回避策があれば教えて下さい。
使用しているシェルは tcsh です。

Aベストアンサー

参考URLに tcsh の man を示します。
ここの最後の方に「制限」という章がありますが、そこにある
「単語は1024文字まで」という制限に引っ掛かってるんでしょうね。

まあ、tcsh であれば、ソースが有るわけですから、ソースを
いじってしまえば良いですよね。

もしくは、コンパイルや実行の際には bash を使う。コンパイルで
make を使っているんだったら、そこでシェルを指定すれば良いだけ
ですよね。

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

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シェルの引数の入力チェックをしたい・・

シェルは初心者のため、ご教授ください。

3つの引数を受け取り、値のチェックを行いたいのですが書き方がよくわかりません・・。

やりたいチェックは、
第1引数は 数字じゃなければエラー
第2引数は 文字列が "YES" か "NO"でなければエラー
第3引数は 日付のフォーマットチェック(YYYY/MM/DD以外はエラー)
です。よろしくお願いします。

Aベストアンサー

1)数字以外を削除して元と同じなら数字のみだとわかる

A=`echo "$1" | sed 's/[^0-9]//g'`
if test "$1" = "$A"
then echo 数字だけ
else echo エラー
fi

2)
if test "$2" = YES -o "$2" = NO
then echo YES か NO
else echo エラー
fi

3)
これは難しい。gnu date (Linux等のdate)を前提とすれば出来ます。
A=`date +%Y/%m/%d -d "$3"`
if test "$3" = "$A"
then echo YYYY/MM/DD形式の日付データ
else echo エラー
fi

gnu date が無いと、大の月・小の月・うるう年などを地道に調べる必要あり。

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に問題がないことを意味しませ...続きを読む

Qsqlplusで表示が変なので、出力を整形したい。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------

上記のように意味不明な形式で出てきます。

例えばこんな風に

select カラム1,カラム2,カラム3 from hoge;

カラム1 1の値
---------------------------
カラム2 2の値
---------------------------
カラム3 3の値

等のように分かりやすく表示できないでしょうか?

ちなみにOracle9iR2を使用しています。
sqlに関するツールは使用できないルールでして、あくまでsqlplusのコマンド上でみやすくしなければなりません。

分かりづらくですいませんが、皆さま、ご教授お願いします。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
-----------------------...続きを読む

Aベストアンサー

SQLPLUSを起動して、

SQL>set linesize 列数

でどうだ。

SQL>show linesize

で確認ができる。


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

人気Q&Aランキング

おすすめ情報