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

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

ただいまの
回答率

90.35%

  • 配列

    545questions

    配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

  • シェルスクリプト

    106questions

シェルスクリプトにおいて、引数を配列名に指定する方法についてお聞きしたいです。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 388

 前提・実現したいこと

シェルスクリプトで引数を配列名にしたい。

 発生している問題・エラーメッセージ

関数で引き渡した引数を関数名にしてPOSCARelementsX..Zのように3つの配列を作成してX..Zの数値をそれぞれ用意したいのですが、引数$4を配列名につけようとするとエラーメッセージ
”./strain.sh: 行 24: POSCARelements[$4]: リストを配列要素に割り当てできません”
が表示されうまく行きません。どうすれば3つの配列にわけられるでしょうか?

X Percent: 3
3
X Interval: 5
5
minus or plus ?: plus
HelloAt
X
Percent: 0.030
Interval: 0.006
1.0
./strain.sh:24: POSCARelements[$4]: リストを配列要素に割り当てできません

 該当のソースコード

AtRegularIntervals(){
    echo "HelloAt"
        echo "$4"
    wariai=`echo "scale=3; $POSCAR*($1*0.01)" | bc |awk '{if($0~/^\./){print "0"$0}else{print $0}}'`
    echo "Percent: $wariai"


    kankaku=`echo "scale=3; $wariai/$2" | bc |awk '{if($0~/^\./){print "0"$0}else{print $0}}'`
    echo "Interval: $kankaku"

    if [ $3 = plus ]; then
      for dankai in `seq 0 $Interval`
            do
                echo "$POSCAR"
                POSCARelements[$4]=("${POSCARelements[@]}"$POSCAR)
                POSCAR=`echo "scale=3; $POSCAR+$kankaku" | bc`
            done

            else 
            for dankai in `seq 0 $Interval`
            do
                echo "$POSCAR"
                POSCARelements[$4]=("${POSCARelements[@]}"$POSCAR)
            POSCAR=`echo "scale=3; (($POSCAR - $kankaku))" | bc`
      done
    fi

        POSCAR=1.0
    return 0
}

#ここでX~Zの値の変動%と間隔、プラス方向マイナス方向を設定
for value in {X..Z};
do
   echo -n "$value Percent: "
   read  Percent[$value]
   echo  ${Percent[$value]}

   echo -n "$value Interval: "
   read  Interval[$value]
   echo  ${Interval[$value]}

   echo -n "minus or plus ?: "
   read  Trancelate[$value]

AtRegularIntervals "${Percent[$value]}" "${Interval[$value]}" "${Trancelate[$value]}" "$value"

done

 試したこと

evalなども試してみましたがうまく行きませんでした。
また、もし回答頂いた方で参考になるサイトやチュートリアルなどがあればお教えいただけると幸いです。(特に変数を他のコマンドに引き渡した時や、他の関数に投げた時の数値の引用方法がわかりません...。)

 補足情報(FW/ツールのバージョンなど)

GNU bash, バージョン 4.3.48

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mather

    2018/07/01 20:09

    echoで出力されたログも質問に追記したほうが良いと思います

    キャンセル

回答 2

checkベストアンサー

0

つeval POSCARelements$4=\("${POSCARelements[@]}"$POSCAR\)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/02 11:45

    ご指摘の通りに作成するとうまく行きました!ありがとうございました!

    キャンセル

  • 2018/07/02 11:52

    POSCARelements$4=\("${POSCARelements[@]}"$POSCAR\)
    この方法を使用し、
    echo ${POSCARelementsX[0]}
    echo ${POSCARelementsX[1]}
    echo ${POSCARelementsX[2]}
    この方法で中身を確認すると、0の位置にある値1つしか出力されないのですが、
    例えばこの配列に5つの値を順々に格納したい場合はどうすれば良いのでしょうか?
    POSCARelementsX[0]に1.006
    POSCARelementsX[1]に1.012
    のように作成したいです。

    キャンセル

0

ちょっと質問が何を言ってるのか分かりませんが、
リストを配列要素に割り当てできません
というのは、文字通りのエラーメッセージで、配列要素POSCARelements[$4]に、リスト("${POSCARelements[@]}"$POSCAR)を代入しようとしていますが、そういう事はできません。

どうすれば3つの配列にわけられるでしょうか? 

は、どういう意味でしょうか?

また、「配列名」という言葉の意味をおわかりでないようですが、foo[bar]という表記に於いてfooが配列名、barは添え字(あるいはインデックス)です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/01 20:20

    ご回答ありがとうございます。
    最終的な目的としては、指定した割合を等間隔で増減させ、それらの値を3つの配列にいれ、ひとつずつ取り出すことを目的としています。
    この場合においてはPOSCARelementsX,POSCARelementsY,POSCARelementsZのように3つの配列を用意し、それぞれに出力結果(1.0,1.006,1.012...のように)をしまう処理を作成しようとしています。その際、$valueにはいっているXYZを配列名に利用することでわかりやすく3つに分けることができないかと考えた次第です。

    キャンセル

  • 2018/07/01 20:30

    > $valueにはいっているXYZを配列名に利用することでわかりやすく3つに分けることができないかと考えた次第です。

    はどういう意味でしょうか?
    私の回答は読んでいますか?

    キャンセル

  • 2018/07/01 21:11

    私の回答というのは
    ”文字通りのエラーメッセージで、配列要素POSCARelements[$4]に、リスト("${POSCARelements[@]}"$POSCAR)を代入しようとしていますが、そういう事はできません”この部分のことでしょうか?
    そういうことはできませんというのが、書き方が間違っているということなのか、そもそも$4のように引数の値を配列名につけること自体が不可能ということなのか、初心者すぎてよくわかっていません。すみません。

    > $valueにはいっているXYZを配列名に利用することでわかりやすく3つに分けることができないかと考えた次第です。

    この文章の意味は、関数を呼び出す前のFor文内でXYZを利用しているため、その値をつかって配列名にPOSCARelementsXのように名前をつけ、3つの配列を作成できるのではないか?と考えた。という意味になります。

    キャンセル

  • 2018/07/01 23:26

    > そもそも$4のように引数の値を配列名
    下記を読んでください。
    > foo[bar]という表記に於いてfooが配列名、barは添え字(あるいはインデックス)です。

    > POSCARelementsXのように名前をつけ、3つの配列を作成できるのではないか?

    できますよ。evalを使えば。

    キャンセル

  • 2018/07/01 23:36

    eval POSCARelements$4='("${POSCARelements[@]}" $POSCAR)'
    とか。

    キャンセル

  • 2018/07/02 11:46

    ありがとうございました!想定した動きをさせることができました!

    キャンセル

  • 2018/07/02 11:53

    他の回答者様にもお聞きしたのですが、
    POSCARelements$4=\("${POSCARelements[@]}"$POSCAR\)
    この方法を使用し、
    echo ${POSCARelementsX[0]}
    echo ${POSCARelementsX[1]}
    echo ${POSCARelementsX[2]}
    この方法で中身を確認すると、0の位置にある値1つしか出力されないのですが、
    例えばこの配列に5つの値を順々に格納したい場合はどうすれば良いのでしょうか?
    POSCARelementsX[0]に1.006
    POSCARelementsX[1]に1.012
    のように作成したいです。

    キャンセル

  • 2018/07/02 12:52

    POSCARelementsXは、配列になります。確認の仕方が悪いのでは?
    その現象の出るコードを書いてください。

    キャンセル

  • 2018/07/02 12:58

    #!/bin/bash

    # 1.0 0.0 0.0
    # 0.0 1.0 0.0
    # 0.0 0.0 1.0

    POSCAR=1.0


    AtRegularIntervals(){
    echo "HelloAt"
    echo "$4"
    wariai=`echo "scale=3; $POSCAR*($1*0.01)" | bc |awk '{if($0~/^\./){print "0"$0}else{print $0}}'`
    echo "Percent: $wariai"


    kankaku=`echo "scale=3; $wariai/$2" | bc |awk '{if($0~/^\./){print "0"$0}else{print $0}}'`
    echo "Interval: $kankaku"

    if [ $3 = plus ]; then
    for dankai in `seq 0 $Interval`
    do
    echo "$POSCAR"
    eval POSCARelements$4=\("${POSCARelements[@]}"$POSCAR\)
    POSCAR=`echo "scale=3; $POSCAR+$kankaku" | bc`
    done

    else
    for dankai in `seq 0 $Interval`
    do
    echo "$POSCAR"
    eval POSCARelements$4='("${POSCARelements[@]}"$POSCAR)'
    POSCAR=`echo "scale=3; (($POSCAR - $kankaku))" | bc `
    done
    fi

    POSCAR=1.0
    return 0
    }

    #ここでX~Zの値の変動%と間隔、プラス方向マイナス方向を設定
    for value in {X..Z};
    do
    echo -n "$value Percent: "
    read Percent[$value]
    echo ${Percent[$value]}

    echo -n "$value Interval: "
    read Interval[$value]
    echo ${Interval[$value]}

    echo -n "minus or plus ?: "
    read Trancelate[$value]

    AtRegularIntervals "${Percent[$value]}" "${Interval[$value]}" "${Trancelate[$value]}" "$value"

    done

    echo "escapeAt"
    cnt=0
    #シェルスクリプトでは0.〜の形で配列にしまえ無いため、置き換えるときに0をつけたす処理を行う。
    #| sed -e 's/^\./0./g'これ

    echo ${POSCARelementsX[0]}
    echo ${POSCARelementsX[1]}
    echo ${POSCARelementsX[2]}



    #sedの行置き換えをつかって3~5行を置換する
    for POSCARxyz in `seq 3 5`
    sed -n ''$POSgyousuu'p' POSCAR


    for dankai in `seq 0 $Interval`
    do
    echo "$POSCAR"
    POSCAR=`echo "scale=3; $POSCAR+$kankaku" | bc`
    done


    kankaku=`echo "scale=3; $wariai/$2" | bc |awk '{if($0~/^\./){print "0"$0}else{print $0}}'`
    echo "$kankaku"
    こちらのコードになります。

    キャンセル

  • 2018/07/02 13:00

    私自身としては
    eval POSCARelements$4='("${POSCARelements[@]}"$POSCAR)'
    この部分のPOSCARelemnts*[@]の*の部分に対応するXYZを指定することで正確に値を入れることができるのでは無いかと考えております。

    キャンセル

  • 2018/07/02 13:04

    > その現象の出るコードを書いてください。
    書き方が悪かったか。
    その現象を確認できるコードを書いてください。
    です。
    実行しただけで、あなたの言っている現象が表示されるコードです。

    キャンセル

  • 2018/07/02 13:25

    #!/bin/bash

    # 1.0 0.0 0.0
    # 0.0 1.0 0.0
    # 0.0 0.0 1.0

    POSCAR=1.0


    AtRegularIntervals(){
    echo "HelloAt"
    echo "$4"
    wariai=`echo "scale=3; $POSCAR*($1*0.01)" | bc |awk '{if($0~/^\./){print "0"$0}else{print $0}}'`
    echo "Percent: $wariai"


    kankaku=`echo "scale=3; $wariai/$2" | bc |awk '{if($0~/^\./){print "0"$0}else{print $0}}'`
    echo "Interval: $kankaku"

    if [ $3 = plus ]; then
    for dankai in `seq 0 $Interval`
    do
    echo "$POSCAR"
    eval POSCARelements$4=\("${POSCARelements[@]}"$POSCAR\)
    POSCAR=`echo "scale=3; $POSCAR+$kankaku" | bc`
    done

    else
    for dankai in `seq 0 $Interval`
    do
    echo "$POSCAR"
    eval POSCARelements$4='("${POSCARelements[@]}"$POSCAR)'
    POSCAR=`echo "scale=3; (($POSCAR - $kankaku))" | bc `
    done
    fi

    POSCAR=1.0
    return 0
    }

    #ここでX~Zの値の変動%と間隔、プラス方向マイナス方向を設定
    for value in {X..Z};
    do
    echo -n "$value Percent: "
    read Percent[$value]
    echo ${Percent[$value]}

    echo -n "$value Interval: "
    read Interval[$value]
    echo ${Interval[$value]}

    echo -n "minus or plus ?: "
    read Trancelate[$value]

    AtRegularIntervals "${Percent[$value]}" "${Interval[$value]}" "${Trancelate[$value]}" "$value"

    done

    echo "escapeAt"
    cnt=0
    #シェルスクリプトでは0.〜の形で配列にしまえ無いため、置き換えるときに0をつけたす処理を行う。
    #| sed -e 's/^\./0./g'これ

    echo ${POSCARelementsX[0]}
    echo ${POSCARelementsX[1]}
    echo ${POSCARelementsX[2]}

    これをこのまま実行するとXYZそれぞれの%とインターバルを入力することになるのですが、Zまで入力した後POSCARelementsX[0]〜[2]を表示させようとすると
    X Percent: 3
    3
    X Interval: 5
    5
    minus or plus ?: plus
    HelloAt
    X
    Percent: 0.030
    Interval: 0.006
    1.0
    1.006
    1.012
    1.018
    1.024
    1.030
    Y Percent: 3
    3
    Y Interval: 5
    5
    minus or plus ?: minus
    HelloAt
    Y
    Percent: 0.030
    Interval: 0.006
    1.0
    .994
    .988
    .982
    .976
    .970
    Z Percent: 3
    3
    Z Interval: 5
    5
    minus or plus ?: plus
    HelloAt
    Z
    Percent: 0.030
    Interval: 0.006
    1.0
    1.006
    1.012
    1.018
    1.024
    1.030
    escapeAt
    1.030
    この最後の1.030のようにXの一番最後の値しか表示されない状況です。

    キャンセル

  • 2018/07/02 13:53

    POSCARelements
    という変数が未定義で、値を参照しています。ちゃんと値を設定してください。

    キャンセル

  • 2018/07/02 13:56 編集

    ああ、わかった。もしかして、
    eval POSCARelements$4+=\($POSCAR\)
    がやりたかったことですか?
    += は配列変数への要素の追加です。

    キャンセル

  • 2018/07/02 13:58

    関数内での値がきちんと設定されていないということですか?

    キャンセル

  • 2018/07/02 14:08

    POSCARelement$4($4にはXYZが入り、3つの配列が作成される想定)にechoで表示された値を格納し、格納された値を参照したいということになります。

    キャンセル

  • 2018/07/02 14:12

    先ほどの配列要素の追加で、うまく動作させることができました!
    長らくお付き合いいただきほんとうに感謝しております!
    ありがとうございました!

    キャンセル

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

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • 配列

    545questions

    配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

  • シェルスクリプト

    106questions