シェル(bsh)でのprintfに関して

このQ&Aのポイント
  • シェル(bsh)で配列関数内のデータをソートして出力する方法を教えてください
  • 配列関数内のデータ数が可変であるため、ファイルに出力する際に余分なスペースが追加されてしまいます
  • スペースが入らないようにする方法や、配列関数内の数だけデータを指定する方法を教えてください
回答を見る
  • ベストアンサー

シェル(bsh)でのprintfに関して

シェル(bsh)でのprintfに関して 配列関数内のデータを「printf」等で、ソートし出力したいと考えております。 配列関数内のデータ数が一定ではない為、多めにし以下の様にすると、 作成されたファイルの右側の方にはその分スペースが追加されてしまいます。 --------------------- # echo ${testfile[*]} AA BB CC DD EE printf "%10s %10s %10s %10s %10s %10s %10s\n" `echo ${testfile[*]}` > testfile ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ← 最大より多めにしておく --------------------- 「testfile」をテキストとして開いたり、vi等で見るとスペースが入ってしまう。 行いたいことは、以下2点です。 ・スペースが入らないようにしたい。 ・出来れば「for」や「while」等を利用し、配列関数内の数だけ「printf」等にて指定したい。  ※見た目や予想より多くデータがあった場合の対策 「printf」に「-v」オプションを指定するとよい。等の記述は調べていた所あったのですが、 現状の環境では指定できないオプションの様です。 恐れ入りますが、知恵をお借りできないでしょうか。 以上、よろしくお願い申し上げます。

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

  • ベストアンサー
  • crossgate
  • ベストアンサー率65% (78/119)
回答No.2

>「awk」は○個目を抜き出す。程度でしか、使用したことがない為、 >NF? i++?C? みたいな感じです。 「-F' '」はデフォルトなんで省略しました。 echo "${testfile[*]}"|awk -F' ' '{for(i=1;i<=NF;i++) if(i<NF) printf("%10s ", $i); else printf("%10s\n", $i);}' なら少し分かりやすいですかね? echo "${XXX}"|awk -F' ' '{print $1}' とかなら良く使われると思うんですが、これって結局  awk -F' '   ・・・ echoの出力をスペースで区切る  '{print $1}'  ・・・ 「'{}'」の中の処理を実行する(この場合はスペースで区切った1個目を出力) ということをしてます。 なので、 echo "${testfile[*]}"|awk -F' ' '{for(i=1;i<=NF;i++) if(i<NF) printf("%10s ", $i); else printf("%10s\n", $i);}' こいつはechoの出力をスペースで区切って、「'{}'」の中の処理(ループ処理)を実行しているだけです。 ループ処理は for(i=1 ; i<=NF ; i++)   if(i<NF)     printf("%10s ", $i);   else     printf("%10s\n", $i); とインデントすると分かりやすいでしょうか? 「i++」は単にループカウンタをインクリメントしているだけです。 「NF」はawkの組み込み変数で、「処理中のレコードにいくつフィールドがあるか」を表しています。 testfile配列の要素が5個なら5ですし、10個なら10になります。 つまりこのループは、  スペースで区切ったフィールドを、1個目からフィールドの終わりまで、   最後のフィールドじゃなかったら"%10s "(最後にスペース)で、   最後のフィールドなら"%10s\n"(スペースなしで最後は改行)で出力する という処理をしています。 awkの制御構文はC言語をベースにしているので結構似ていますね。 >使用している環境はLinuxです。 その為、sh=bashとの事でしょうか。 >${testfile[*]} の様な書き方が、shでは不可ならそこから確認する必要あり! >なんですね。。 LinuxのデフォルトはBourne Shellではなくてbash(Bourne Again Shell)になります。 (cshはtcshになっていたりもするし。。。) 質問に「bsh」と書かれていたので、Bourne Shellの方だと思ってました。 LinuxにBourne Shellを入れてその上で動かしたいという訳ではないですよね? bash(Bourne Again Shell)ならOKです。 (Unix系の/bin/shはBourne Shellで、Linuxの場合は/bin/bashへのリンクなので、 Linuxでshというと実体はbashになります) 私もLinux環境(bash)で#1が動くことを確認してます。 参考までに、bashには配列がありますが、Bourne Shellには配列がありません。 evalを使って擬似的に配列を実現します。(全然配列ではないんですが。。。) 当然、evalを使う場合は echo "${testfile[*]}"|awk -F' ' '{for(i=1;i<=NF;i++) if(i<NF) printf("%10s ", $i); else printf("%10s\n", $i);}' も使えないです。 この辺りをご参考に。 http://cl.pocari.org/2003-01-29-2.html http://d.hatena.ne.jp/anmino/20091019

nagaraja
質問者

お礼

その後、この使用方法を他でも利用させて頂いております。 大変助かりました。ありがとうございました。

nagaraja
質問者

補足

crossgate 様 噛み砕いた説明ありがとうございます。 週末に時間がとれたため、再確認を行いました。 記述の仕方に関しては、まだ微妙ですが、少しづつなれて行こうと考えております。 > LinuxにBourne Shellを入れてその上で動かしたいという訳ではないですよね? 元々、スクリプトを作成する際、「sh」にて記述しようと考え行っていました。 この場合、出来るだけ「sh」として振舞うよう、エミュレートする。 的な事が記載されていた為、タイトルで「bsh」としました。 ※現に「${PIPESTATUS[@]}」等は「sh」とした時は使えなかった為。 この辺の認識も違ったようなので、これからの課題としています。 ありがとうございました。

その他の回答 (1)

  • crossgate
  • ベストアンサー率65% (78/119)
回答No.1

これってbshじゃなくてbashじゃない?とは思いますが。。。 こんな感じでどうですか。 echo "${testfile[*]}"|awk '{for(i=1;i<=NF;i++) if(i<NF) printf("%10s ", $i); else printf("%10s\n", $i);}'

nagaraja
質問者

補足

crossgate 様 返事が遅くなり申し訳ございません。 記述頂いた内容にて、行いたいことが出来ました。 ありがとうございます。 「awk」は○個目を抜き出す。程度でしか、使用したことがない為、 NF? i++?C? みたいな感じです。 なぜ成り立っているのかも微妙な為、提示頂いた記述を参考に 少し勉強したいと考えます。 使用している環境はLinuxです。 その為、sh=bashとの事でしょうか。 ${testfile[*]} の様な書き方が、shでは不可ならそこから確認する必要あり! なんですね。。 思いもつかなかった為、助かりました。 本当にありがとうございました。

関連するQ&A

  • 【PHP】printf()関数の小数点以下の扱い方

    printf()関数で以下のような記述をしました。 関数の引数を計算すると単純で 5 × (1 - 0.35) で結果は 3.25 となります。 これを$%.1f によって出力するため小数点以下は1桁です。 桁数を指定した場合、指定し桁数以下は「四捨五入」されると思っていました。 よって、自分では Price: 3.3 と出力されると考えていましたが 実際には Price: 3.2 と表示されます。 ちなみに 3.25 を round() 関数で使うと 3.3 と返ってきます。 printf()関数で小数点以下の桁数をしてした場合、四捨五入、切り上げ、切り捨て いずれでもない値が返ってくるのでしょうか? このような小数点以下の桁数を扱う方法はPHPの他の関数でも使われるのでしょうか? この方法の呼称というか名称というのはあるのでしょうか? 初学者です。分かりやすく教えていただければ幸いです。 よろしくお願いいたします。! <表示結果> Price: $3.2 3.3 <?php $price = 5; $off = 0.35; printf("Price: $%.1f", $price * (1 - $off)); echo "<br>\n"; echo "<br>\n"; echo round(3.25, 1); ?>

    • ベストアンサー
    • PHP
  • シェルスクリプトでのスプリット

    bshでのスプリットはどのようにするのでしょうか? ファイルAには、スペース区切りで以下のデータが入ってます。 # cat fileA parameter1 parameter2 parameter3 parameter1x parameter2x parameter3x ....... .. 上記のファイルでparameter2の部分(真ん中のデータ)を 取得するには、どのようになりますか? 以上宜しくお願いします。

  • 関数の戻り値として文字列を返して、printfで出力させることはできますか?

    いま、引数の数値によって、文字列を返すという関数を作り、それをprintf関数で出力したいと考えているんですが、どうやって作ればいいのかわかりません。 char data_2_dtmfdata(u8 getdata) { switch(getdata) { case 0x01: //tone"1" return "KEY_1"; case 0x02: //tone"2" return "KEY_2"; case 0x03: //tone"3" return "KEY_3"; } } このような感じで関数を作成して、 printf("%s",data_2_dtmfdata(data)); printf関数でこのように設定してあげれば”KEY_1”とか”KEY_3”とかの文字列を出力してあげられるのでしょうか?

  • phpでのセレクトボックスの値を配列で指定

    セレクトボックスの値をループで繰り返してvalueを設定しているのですがvalueの数が多くなればかなり見づらく 修正もしにくいのでvalue値を配列などで指定したいと思っています。 その場合、どのようにしてvalue値に配列を設定すればよろしいのでしょうか。 また配列でvalueを設定した場合[selected]などで初期値を設定する方法も分からなかったので 何かわかりやすくかつ少ない行数で胥吏できる方法があればご教授お願いします。 <?php for ($data = 1; $data < 5; $data++) { ?> <tr><td> <select name="test<?php echo $data?>"> <option value=1>1 <option value=2>2 <option value=3>3 <option value=4>4 <option value=5>5 <option value=6>6 <option value=7>7 <option value=8>8 <option value=9>9 <option value=10>10 </select> <?php } ?> ※option valueが20とか30とかになるとかなり見づらい処理かなと思います。 配列を変えるだけでいいようにしたいです。

    • 締切済み
    • PHP
  • printfの中でラジオボタンを使いたい

    日ごろからお答えくださっている皆様ありがとうございます。 現在PHPを使ってHP作成中の初心者です。 初歩的な問題なのかもしれませんがこの種の質問で参考になりそうなものはネットでは調べられなかったので質問させていただきます。 以下のような形でラジオボタンを使おうとしているのですがエラーが出てしまいます。 $sql = mysql_query('SELECT `市区町村`, COUNT(`市区町村`) AS `count` FROM `estate` GROUP BY `市区町村`'); while ($row = mysql_fetch_object($sql)) { echo '<table border="1" cellspacing=0 cellpadding=5 width=780>'; printf('<input type="radio" name=%s value=%s/> (%d)', $row->市区町村, $row->count); echo '</table>'; } エラーメッセージは以下の通りで、48行目はprintfを使用している行です。 Warning: printf() [function.printf]: Too few arguments in C:\xampp\htdocs\Home_Search\src\search\search1.php on line 48 以上、よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • 3バイト文字(UTF-8)をprintfで等幅表示をするには?

    64BIT環境のLINUX、gcc で開発をしております。 表題の件ですが、UTF-8 は3バイト文字が多いため、strlenの戻り値と、printf で表示したときの画面上の桁数が一致しません。 そのため、下記のようなプログラムを実行すると >> int main() { char* s = "あいうえお"; printf("%20s\n", s); return 0; } ... あいうえお << と、画面上で15桁で表示されます。 つまり、文字列中のUTF-8の文字数分、表示幅がフィールド幅より短くなるわけです。 現状、文字列中の UTF-8文字の数を数える関数を作成し、以下のように対処しております。 >> int strUTF8Count(const char* s) { int notAsciiCount = 0; while(*s++) { if (!isascii(*s)) ++notAsciiCount; } return notAsciiCount / 3; } int main() { char* s = "あいうえお"; printf("%*s\n", 20 + strUTF8Count(s), s); return 0; } << これで、現状動いておりますが、strUTF8Count関数の作りが雑で、ascii でなければ UTF-8 と仮定しているし、UTF-8 であれば、3バイト文字と仮定してしまっています。 printf もかなりみづらいですし、何かもっとスマートな方法はないものでしょうか? UTF-8 の扱いとしては一般的なものと思われますが、ネット上を検索しても有効な対処が見つかりませんでした。 どなたかよい知恵をお持ちの方がいらっしゃいましたら、知恵を分けてくれるようお願いします。

  • c#でC言語のstrtokに相当する関数は何か

    文字列から指定した文字でデータを区切る関数strtokがC言語にはある これに相当するC#の関数は何か 例えばCでは以下のように書く。 char data1[]= " 123 , 456 Yamada " ; char *token ; strtok( data, " ," ) ; /* スペースとカンマを区切りに文字列を抽出 */ token = strtok( str, " ." ); printf(" token chat = %s\n", token ) ; while ( token != NULL ) { token = strtok( NULL," ." ); if ( token != NULL ) printf(" token chat = %s\n", token ) ; } これに相当するc#のSplit関数を使用すると 不要な空白を取り出しているようである 知っている方がおりましたら、教えて下さい。

  • 力を貸してください

    int配列 data1 のデータと int配列 data2 のデータ、 および、 data1,data2 の「要素数」kosuu を関数 times に 引数として渡す。\\\ 関数 times 内では、 data1[i] と data2[i] とによる 「掛け算」を計算し、その結果を配列data3[i]に蓄えるものとする。 main関数内では、関数 times で計算した「掛け算」が 格納されている配列データdata3[i](data1[i]とdata2[i]の積) をprintf表示させるプログラムを作成してください。

  • PHPのセレクトボックスの初期値について

    phpのセレクトボックスの値を配列で指定したのですが初期値の表示がうまくいきません。 以下は現在のソースです。 $start_time[$j]はDBの取得値で取得配列と表示配列が一致するものを初期表示する というコードが以下になります $time_array = array( "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23" ); for( $a=0; $a < count( $time_array ); $a++){ $selectedStartTime =($time_array[$a] == $start_time[$j])?" selected":""; $startTimeSelectBox .= "\t<option value=\"{$time_array[$a]}\"{$selectedStartTime}>{$time_array[$a]}</option>\n"; } 疑問点ですが別条件で(たとえば$start_time[$j]にデータが0の時)配列の指定した値を選択したいです。 下記のようにそれぞれのvalue値の時に条件を指定すればできるのですが配列の時には どのように初期値を設定すればいいかわかりません。        <option value="0" <?php if($start_time[$j] == "0") { echo "selected"; } ?>> 0 <option value="1" <?php if($start_time[$j] == "1") { echo "selected"; } ?>> 1</option> <option value="2" <?php if($start_time[$j] == "2") { echo "selected"; } ?>> 2</option>         ・         ・         ・         ・ 条件を指定したときに初期値を設定したいです。どのように実装すればいいでしょうか。 よろしくいお願いします。

    • ベストアンサー
    • PHP
  • printfの小数点以下の表示桁数につい

    Java超初心者です。宜しくお願い致します。 System.out.printf("%8f\n",15.8); は8桁表示のはずですが、 実行すると、 15.800000 と、いう風に9桁になります。 詳しい方はきっと当たり前と思うと思いますが、 小数点以下の桁数がどういう基準で決められるのか、 つまりゼロ(0)がいくつ並ぶか、というのがよくわかりません。 %12f に変更すると、    15.800000 と、左側にスペースが3つ入ります。 12桁と指定しても、小数点以下のゼロが5つだから、左にスペースが3つ入るわけですよね。 結局、小数点以下の桁数を指定していないのに勝手にゼロが並ぶので、 表示は実行してみるまでどうなるか解らない、という状況です。 規則というか、ルールを解りやすく教えて頂けると嬉しく思います。 宜しくお願い致します。

    • ベストアンサー
    • Java

専門家に質問してみよう