• ベストアンサー

【シェルスクリプト】 ローカル変数、グローバル変数

シェルスクリプトのローカル変数、グローバル変数の取り扱いで迷っています。 ---------------- #!/bin/bash count=0 cat file | while read i do count=`expre $count + 1 ` done echo $count ---------------- fileの中身をcatで流して、それを一行ずつ読み込みます。 そのつど、count の値を増やしていくようにしたいのですが、最後の出力値は0となります。 cat→whileで読み込ませて処理している間はローカル変数として扱われているのでしょうか。 またそうであるならば、シェルスクリプトでグローバル変数を明示的に宣言するにはどうのようにすればいいのでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • ballville
  • ベストアンサー率47% (233/487)
回答No.1

まず、bashの変数は何も指定しなければ、グローバル変数として 扱われます。 ですので、グローバル変数をわざわざ宣言する方法はありません。 ローカル変数は、関数の中では使用可能ですが、'local'で宣言 しなくてはなりません。 下記ページの局所変数の項目を参照してください。 http://www.fireproject.jp/feature/bash/basic/variable.html それでは、なぜ、skip_jackさんのスクリプトで、 $countの値が変わらなかったのか、というと、 パイプの後でwhile文を起動するときにサブシェルが 起動されてしまったからです。 下記参照 http://dsas.blog.klab.org/archives/50703133.html というわけで、上記ページのコメントに書かれている 名前つきパイプの手法を使って、 次のようにしてみたらどうでしょう。 #!/bin/bash count=0 while read i do count=`expr $count + 1 ` done < <(cat file) echo $count

skip_jack
質問者

お礼

目から鱗です。 参考になるURLも教えていただきましてありがとうございました。 大変感謝しております。

その他の回答 (1)

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.2

bashの拡張機能を使うと#1さんの書いた方法もありますが、shの基本機能だけで行くなら、パイプを使わなければいいので、 count=0 while read i do count=`expre $count + 1 ` done < file echo $count

skip_jack
質問者

お礼

ご回答ありがとうございます。 パイプを使った場合の動作をまったく理解していませんでした。 教えていただきました方法を参考にスクリプトが組めそうです。

関連するQ&A

  • シェルスクリプト

    2月14日頃質問のあった”UNIXのシェルスクリプトを使用してテキストファイルのある列にある特定の文字列を条件としてその行を出力するということをやりたい”を下記のように作ってみました。問題ないか逆質問の形で投稿します。(ルール違反かもしれませんが質問が締め切られているので・・・) #!/bin/bash CAT=YAHOO while read LINE do echo $LINE > tmp.txt DOG=`cut -d" " -f2 tmp.txt` if [ "$CAT" = "$DOG" ] then echo "$LINE" fi done < catalog.file

  • シェルスクリプトの変数

    Bシェルのスクリプトで入力した情報を書き出すというスクリプトで詰まってしまったので、アドバイスをお願いできますでしょうか? #!/bin/sh # COUNTER変数のリセット COUNTER=1 # 繰り返す回数を入力 read KURIKAESHI # KURIKAESHIで入力した回数入力を受け取り、出力する while [ $COUNTER -le $KURIKAESHI ];  do # 必要な情報の入力("NYUURYOKU_{COUNTER変数の数字}"の変数に入れる)   read NYUURYOKU_$COUNTER   echo "$NYUURYOKU_$COUNTER" ←※ココ   COUNTER=`expr $COUNTER + 1` done 上記のようなスクリプトを書き、"$NYUURYOKU_$COUNTER"の値を出力したいのですが、何かよい方法はありますでしょうか? echo "$NYUURYOKU_$COUNTER" と記述しただけでは、$NYUURYOKU_と$COUNTERとバラバラになってしまいます。(当然っちゃ当然ですが・・・) 何かよい方法がありましたらご教授お願いいたします。

  • シェルスクリプト

    while文のシェルスクリプトでエラーが出て困っています。 どうすればいいでしょうか? 回答の程宜しくお願い致します。 #!/bin/bash count=1 while[$count -le 5] do touch "y$count" ls -l "y$count" coun ='expr $count+1' done [root@Linux root]# . makefile bash: while[1 -le 5]: command not found bash: makefile: line 4: syntax error near unexpected token `do' bash: makefile: line 4: `do'

  • シェルスクリプト 一つのふくすう変数から値を取る方

    いつもありがとうございます。 NICという変数にはネットワークアドレスが2つ入ってます。 NIC= 192.168.0.1 127.0.0.1 下記のスクリプトで上記2つのアドレスを取ろうと思ってます。 ==========test.sh================ while read LINE; do echo $LINE done < ${NIC} =============================== しかし下記のようなエラーになります。 変数の取り出し方が悪いのだと思います。 =============================== ./test.sh: 192.168.0.1 127.0.0.1: そのようなファイルやディレクトリはありません 恐れ入りますが正しいスクリプトをご教授くださいますようお願いします。

  • シェル変数の有効範囲に関して質問させて下さい。

    シェル変数の有効範囲に関して質問させて下さい。 while文にて代入した変数を、その後も使用したいと考えております。 以下、試してみた内容です。 ---------------------- # cat /WORK/test_clice sda sda1 sda2 sda3 sda4 sda5 sda6 sda7 sda8 sdb # declare -a clice # declare -i count # cat /WORK/test_clice | while read LINE; do count=`expr $count + 1`; clice[${count}]=${LINE}; echo ${clice[${count}]} ; done sda sda1 sda2 sda3 sda4 sda5 sda6 sda7 sda8 sdb # echo ${clice[1]} # ---------------------- 有効範囲の為、引き継がれていないのかな?と考えております。 試しに、「set」や「export」を使用してみたのですが、旨く行きませんでした。 ※使い方が悪い? 基本的な内容となり恐縮ではございますが、知恵をお借りできませんでしょうか。 よろしくお願い致します。

  • bashシェルスクリプトで変数を使う

    bashシェルスクリプト内で変数を使いたいです。 Linux内の設定ファイルを参考に、 ・変数名=その内容、で設定 ・${変数名} 、で呼び出す だと判断し、以下のように使っています。 #!/bin/bash WORK=/home/aaa/ cd ${WORK} その後検索したところ、 「呼び出すには、$変数名 のように記述する」との説明を見かけ、 実際$の後に変数名を付けるだけでも認識したのですが、 { }は付けても付けなくてもよいのでしょうか。 { }が必要な場合もあるのでしょうか。

  • bashにおける $[算術式] とは?

    ShellShock脆弱性で世間を騒がせているbashについて教えてください。 * 質問内容は脆弱性とは関係ありません :) 下記のコードは1から5までカウントする単純なwhileループです。 #!/bin/bash count=1 while [ "$count" -le 5 ]; do echo $count count=$[count+1] # ループ変数をインクリメント done ループ変数をインクリメントする書き方は色々ありますが、上記のような書き方は初めて見ました。 この $[count+1] の角括弧は何なのでしょうか? インタプリタシェルをdashにするとエラーになるので、bash特有の記述だとは思うのですが・・・ よろしくお願いします。

  • 行頭が数字の行を表示するシェルスクリプト

    最近シェルスクリプトの勉強をはじめまして、一度自分で作ってみようと思い 行頭が数字の行を表示するシェルスクリプトを書いてみました。 が、うまく出来ません。 表示させたいファイルは字幕ファイルの始めの10行程度で内容は以下の様になってます 1 00:00:03,600 --> 00:00:07,195 xxxxxxxxxxxxxx xxxxxxxxxxxxxx 2 00:00:07,360 --> 00:00:09,635 xxxxxxxxxxxxxx xxxxxxxxxxxxxx     ・       ・     ・ xxxxxxxxxxxxxの部分には英語の台詞が入ります。 以下が自分で作ってみたスクリプトです。 #!/bin/bash while read Line do if [ "$Line" eq [0-9][0-9] ] then echo $Line else : fi done < $1 表示させたいのは行頭が数字の行なので自分の望む結果は 1 2 3 ・ ・ ・ です。 初歩的な間違いかもしれませんが、自分にはどこが間違っているのか分かりません。 酷いスクリプトかもしれませんが、一応完成させてみたいのでご指導お願いしますm(_ _)m

  • シェルスクリプトの1行目

    シェルスクリプトの1行目に#!/bin/bashと書くと思うのですが 環境によってbashのパスが違うのですが、そのような場合は2つ書くことは可能でしょうか? 例えばLinuxなんかは#!/bin/bashですよね? Macだと#!/bin/bashだと3系なので古いので5系をインストールすると#!/usr/local/bin/bashになるんです 1台のパソコンで使ってる分には問題ないですが他の環境で使う場合2つ書くにはどうしたら良いでしょうか?

  • シェルスクリプトからPHP実行

    シェルスクリプト(bash)内で、以下のようにPHPを呼んだ場合、 その次の処理がPHPの終了を待たずに実行されるようなのですが、 どうしてでしょうか? #!\bin\bash /usr/local/php4/bin/php /home/test.php echo "test!" 以上 なぜか test! という表示がPHPの処理中に出るように思えます。

専門家に質問してみよう