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

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

新規登録して質問してみよう
ただいま回答率
85.47%
シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

配列

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

Q&A

解決済

2回答

950閲覧

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

johntitor1997

総合スコア8

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

配列

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

0グッド

0クリップ

投稿2018/07/01 10:43

編集2018/07/01 11:13

前提・実現したいこと

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

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

関数で引き渡した引数を関数名にして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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mather

2018/07/01 11:09

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

回答2

0

ベストアンサー

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

投稿2018/07/01 13:08

hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

johntitor1997

2018/07/02 02:45

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

2018/07/02 02: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 のように作成したいです。
guest

0

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

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

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

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

投稿2018/07/01 11:11

編集2018/07/01 11:14
otn

総合スコア84710

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

johntitor1997

2018/07/01 11:20

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

2018/07/01 11:30

> $valueにはいっているXYZを配列名に利用することでわかりやすく3つに分けることができないかと考えた次第です。 はどういう意味でしょうか? 私の回答は読んでいますか?
johntitor1997

2018/07/01 12:11

私の回答というのは ”文字通りのエラーメッセージで、配列要素POSCARelements[$4]に、リスト("${POSCARelements[@]}"$POSCAR)を代入しようとしていますが、そういう事はできません”この部分のことでしょうか? そういうことはできませんというのが、書き方が間違っているということなのか、そもそも$4のように引数の値を配列名につけること自体が不可能ということなのか、初心者すぎてよくわかっていません。すみません。 > $valueにはいっているXYZを配列名に利用することでわかりやすく3つに分けることができないかと考えた次第です。 この文章の意味は、関数を呼び出す前のFor文内でXYZを利用しているため、その値をつかって配列名にPOSCARelementsXのように名前をつけ、3つの配列を作成できるのではないか?と考えた。という意味になります。
otn

2018/07/01 14:26

> そもそも$4のように引数の値を配列名 下記を読んでください。 > foo[bar]という表記に於いてfooが配列名、barは添え字(あるいはインデックス)です。 > POSCARelementsXのように名前をつけ、3つの配列を作成できるのではないか? できますよ。evalを使えば。
otn

2018/07/01 14:36

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

2018/07/02 02:46

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

2018/07/02 02: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 のように作成したいです。
otn

2018/07/02 03:52

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

2018/07/02 03: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" こちらのコードになります。
johntitor1997

2018/07/02 04:00

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

2018/07/02 04:04

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

2018/07/02 04: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の一番最後の値しか表示されない状況です。
otn

2018/07/02 04:53

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

2018/07/02 04:57 編集

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

2018/07/02 04:58

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

2018/07/02 05:08

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

2018/07/02 05:12

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問