個人事業主の方必見!確定申告のお悩み解決

cshスクリプト内での”ヒアドキュメント”とパイプライン

cshスクリプト内で、
1)比較的大量の入力を必要とするコマンドcommand1
2)command1の出力をawkにかけて整形する

ことをしたいのです。ここで、条件として、一時ファイルを作らないという制約があります。

ここで、ヒアドキュメントというのでしょうか?
command1 <<EOF
very very long text
very very long text
very very long text
very very long text
EOF

を用い、command1の入力とします。
そして、command1の標準出力をawkにかけたいのです。

そこで

#!/bin/csh

( command1<<EOF
very very long text
very very long text
very very long text
very very long text
EOF)| awk '............'

とかやってみましたが、うまくいきません。

command1 <<EOF | awk '....'
very very long text
very very long text
very very long text
EOF

もだめです。
別に、<<EOFにこだわるつもりはないのですが、cshスクリプト内で、かつ一時ファイルの作成をせずに、
このようなことをやる方法はあるでしょうか? 入出ストリームの切り替えとかでできそうな木もするのですが、できればそれはなしでお願いします。

なんでcshわざわざこんなことをやるんだ、一時ファイル作ればいいじゃん、という意見ごもっともですが、cshの理解のため、あえてやってみたいのです。

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

A 回答 (1件)

とりあえず素直にやるなら、



(command | awk '/bar/{print}') <<EOF
foo
bar
baz
EOF
    • good
    • 0
この回答へのお礼

ありがとうございました。
あまりきれいではないですが、ここらへんがshプログラミングの限界なのでしょうね。
shやtcshのトークンの分解、""、''、``の置換過程、<>の構文解析など勉強していきたいと思います。

お礼日時:2010/07/14 08:24

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

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

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

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

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

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

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

のようなセットを行い、

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

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

Aベストアンサー

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

aaa='bbb
ccc'

QUNIX(Cシェル)での数値判断での条件分岐がうまくいきません。

いつもお世話になっております。
宜しく御願い致します。

if文で数値判断により条件分岐をしようと思ってます。

条件は”0<変数<=20”(仮)で、エラーだと警告文表示後に変数入力部に戻したいのです。

変数を画面上から”変数 = $<”で読み込み、処理をしたいのですが、うまくいきません。

整数値だとうまく行く方法を見つけましたが、小数値が入るとNG、小数値でもうまく行く方法を見つけました(bcを使用)が、文字列が入力されるとNG、と行き詰まってしまいました。

入力値としては小数値を期待しているのですが、操作する人が間違って”3..2”や”2 5”、”4rr”等が入力された場合も偽の判断をもって処理を戻したいのですが、ifの形式がおかしいとか、文法上のエラーがあると表示され、うまく戻ってくれません。

なにか良い方法はないでしょうか?

要は、if(変数 > 0 && 変数 <= 20) then で変数の値が文字列、小数、整数問わずに処理をしたいだけなんですが・・・。

どうぞ宜しく御願いします。

Aベストアンサー

expr等を使って正規表現で判断するしかないでしょうね。\| の前が小数値、後ろが整数値のチェックです。
expr以外でも正規表現が使えるコマンドなら何でもいいですが。

expr "$var" : '[0-9][0-9]*\.[0-9][0-9]*$' \| "$var" : '[0-9][0-9]*$' >/dev/null

if( $status == 0 ) then
 正常処理
else
 エラー処理
endif

QCシェル内でBシェルの様な関数の記述方法はありますか?

タイトル通り、Cシェル内でBシェルの様な関数の記述方法はありますか?

Bシェルで言う所の以下の様な記述方法です。

関数()
{

}

OSはSolarisです。

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

Aベストアンサー

cshには関数はありません。tcshも同じだと思います。
関数部分を別ファイルにして、sourceコマンドで呼び出すくらいしかないでしょう。
cshは大規模なスクリプトには向かないと思います。

Qcshで拡張子を除いたファイル名を取得したい

cshにてファイル名から拡張子を除いた文字列を取得したいと思っています。

例えば
abc.txt -> aaa
defg.log -> defg
といった具合に。

*ファイル名の長さは固定長ではないです。
*拡張子の長さもできれば3文字固定にはしたくないです。(無理なら固定でもやむを得ませんが)

何か簡単でいい方法はないものでしょうか?
知恵を貸してください。
よろしくお願いします。

Aベストアンサー

cshですよね。

set f = aaa.txt
echo $f:r

Qシェルの実行について

シェル、コマンドを実行に関して質問があります。
シェル名だけ「シェル名」だけで実行できたり「./シェル名」としないと実行できなかったりしますが、この違いはどこからくるのでしょうか?
また、「csh シェル名」とするばあいもありますが、これらの明確に違い(使い分け)が分かりません。
ご教授の程宜しくお願いいたします。

Aベストアンサー

パスを省略すると、環境設定のPATHに記述された順にコマンドを探しに行きます。

「csh シェル名」とするのは、cshにファイルを渡しています。
先頭のcshを省略するためには、ファイルの先頭に #!/bin/csh (環境に応じて変更要)の記述がある
ことと、そのファイルに実行権限がついていることが必要になります。

なお、「./シェル名」とすることは、PATHによって意図したコマンドとは別に存在する
コマンドを呼んでしまうことがないようにする良いマナーです。
特にrootではコマンドはフルパスで実行するよう心がけましょう。

コマンドの場所は、 which で探すことができます。
PATHによって複数のコマンドが呼べる場合は、whereis で探すこともできます。

Qcshで文字列分割

ヤマトです。

cshの文字列分割について質問します。
環境はRed Had Linux7.2です。

set DATA = hoge1;hoge2;hoge3
のデータを";"区切りでDATA_ARR(配列)に入れたいのですが、分かりません。
調べた所、[awk]と[split]を使えばできるようなのですが、
実際どのようにSHに記述していいか分かりません。
n = split(DATA,DATA_ARR,";")
をどのように記述したらよいのでしょう?

教えて頂けると有り難く思います。宜しくお願いします。

Aベストアンサー

こんにちは、ヤマトさん。

csh の配列というのは、例えば DATA が「foo;bar;baz」であったとき、
DATA_ARR には「foo bar baz」という値を入れたいということでいいでしょうか。

split を使えばこのようになりますか。最後には Control-D を押す必要があります。
この例では split の結果は配列 A の中に格納されます。
「DATA=$DATA」はシェル変数 DATA の値を
AWK で用いる変数 DATA に代入するという意味です。

set DATA_ARR=`awk 'END{split(DATA,A,";");print A[1],A[2],A[3]}' DATA=$DATA`

split を使わない別解として、標準入力を用い

set DATA_ARR=`echo $DATA | awk 'BEGIN{FS=";"}{print $1, $2, $3}'`

とも書けます。こちらは C-d は不要です。

BEGIN 節の中の「FS」とはフィールド区切り文字(field separator)の意味で、
AWK は $0 をこの値によって自動的に split してくれます。

なお、FS については BEGIN 節の中で記述せず、
「-F\;」のようにAWK へのオプションとしても指定できます。
(「;」をエスケープしていることにご注意)

「OFS」という出力フィールド区切り文字(output FS)もあり、
print などの出力はこれを挟んで表示されます。
初期値はスペースで、上記の例でもこの初期値を利用しています。

結果は「echo $DATA_ARR[1]」などとしてご確認ください。

独習されているようですので、いい参考書が必要でしょう。
「LINUX クイックリファレンス(第2版)」(オライリー・ジャパン)がお勧めです。
この1冊の中に各種シェルや awk, perl、GNU コマンドなどが要領よく解説されています。
お値段は高めですが、それだけの値打ちはあると信じます。
http://www.oreilly.co.jp/BOOK/linuxnut2/

AWK の参考書としては同じくオライリー・ジャパンの「sed&awk プログラミング 改訂版」
(Dougherty, Robbins 共著、福崎 俊博訳)か、
「プログラミング言語 AWK」(エイホ・カーニハン・ワインバーガー共著、
足立高徳訳/シイエム・シイ)がいいでしょう。
ちなみに「AWK」の名前の由来はこの三人 Aho, Weinberger, Kernighan の
頭文字を取ったものです。
http://www.oreilly.co.jp/BOOK/sedawk/
http://www.amazon.co.jp/exec/obidos/ASIN/4901280406/ref%3Dase%5Fseshopcom-22/250-8600902-9060234

スクリプト言語として AWK もいいのですが、基本的にフィルタ言語ですから
制御構造が標準入力を読み込むためのループに縛られる傾向があります。
今から学ぶとしたら、Ruby や Perl または Python の方がよりやり甲斐があると思います。
特に私の好きな Ruby ではこのように書けます。

ruby -e "print '$DATA'.split(/;/).join(' ')"

(ba)sh においては以下のようにしてください。

ruby -e "print \"$DATA\".split(/;/).join(' ')"

join は split の逆で、配列要素を区切り文字で挟んだ文字列を返します。

split の括弧の中身がシンプルなのがおわかりでしょうか。
左から右へすんなりと処理が進んでいくのは、
Ruby の「オブジェクト指向」の御利益なのです。
http://www.ruby-lang.org/ja/
http://www15.web24.jp/~c01763n1/rubytips/

最後にちょっとお節介。
csh を使ってみて、やっぱり込み入った引用符の処理が
(ba)sh に比べて洗練されていないと感じました。
最後の Ruby の実行例でも、''で囲まれて展開されないはずの $DATA が
実際には展開されたり、エスケープしたはずの「"」が
実際にはされなくてエラーになったりしました。
bash ではちゃんと思い通りの結果が得られます。

シェルスクリプト言語としては、sh をお使いになった方が
リダイレクションなどいろいろと楽だと思います。
http://faqs.jmas.co.jp/FAQs/csh-whynot-jp

bash でもバージョン2から配列が使えるようになっています。
表記は「${DATA_ARR[1]}」のようになります。あ、「man gawk」も忘れずに。

http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/awk/intro/

参考URL:http://aoki2.si.gunma-u.ac.jp/Hanasi/Algo/awk.html,http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_toc.html

こんにちは、ヤマトさん。

csh の配列というのは、例えば DATA が「foo;bar;baz」であったとき、
DATA_ARR には「foo bar baz」という値を入れたいということでいいでしょうか。

split を使えばこのようになりますか。最後には Control-D を押す必要があります。
この例では split の結果は配列 A の中に格納されます。
「DATA=$DATA」はシェル変数 DATA の値を
AWK で用いる変数 DATA に代入するという意味です。

set DATA_ARR=`awk 'END{split(DATA,A,";");print A[1],A[2],A[3]}' DATA=$DATA`

...続きを読む

Qcshの条件式について教えてください

cshで該当ディレクトリにファイルがなければOK、あればエラーというような処理をしようと思っています。

しかし、下記のような記述ではうまくできません。
1)
***************************
if ( -e $DIR/*.* ) then
echo "NG"
exit 1
else
echo "OK"
endif

exit 0
***************************

if文でなく、外にだせばうまくいくのですが...
2)
***************************
test -e $DIR/*.*
if($status == 0) then
echo "NG"
exit 1
else
echo "OK"
endif
exit 0
****************************

if ( test -e $DIR/*.* ) then...
でもだめでした。

どうにかしてif文で一発判定をしたいと思っているのですが、正しい記述方法を教えてください。

よろしくお願いします。

cshで該当ディレクトリにファイルがなければOK、あればエラーというような処理をしようと思っています。

しかし、下記のような記述ではうまくできません。
1)
***************************
if ( -e $DIR/*.* ) then
echo "NG"
exit 1
else
echo "OK"
endif

exit 0
***************************

if文でなく、外にだせばうまくいくのですが...
2)
***************************
test -e $DIR/*.*
if($status == 0) then
echo "NG"
exit 1
else
echo "OK"
endif
exit 0
****...続きを読む

Aベストアンサー

一発判定ではなくても、警告が出なければ良いんですよね?

***************************
set FILE = (`ls $DIR | grep *`)
if ( $#FILE != 0 ) then
echo "NG"
exit 1
else
echo "OK"
endif

exit 0
***************************

これなら警告でないはずです。

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

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

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

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

Aベストアンサー

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

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

Qシェルスクリプトの実行、「source」と「.」の違いについて

bashのシェルスクリプトを書いています。
当方、Mac Snow Leopard を使っているため、seq コマンドがデフォルトでは使えません。
そこで、.bashrc 内に、seq 関数をあらかじめ自分で定義して、他で使い回したいと思っています。
.bashrc の中に、
function seq() {
i=$1
while [ $i -le $2 ] ; do
echo $i
let i=$i+1
done
}
と、関数を定義しました。
seq 関数をターミナル上で実行すると、
>seq 0 2
0
1
2
と正しく、表示されます。次に、

#!/bin/sh
seq 0 2

と記述したシェルスクリプト(temp.sh)を「source」で実行すると、
>source temp.sh
0
1
2
と正しく、表示されますが、「.」で実行すると、
>./temp.sh
./temp.sh: line 2: seq: command not found
と言われます。
どのような理由によってこの違いが出るのでしょうか??

bashのシェルスクリプトを書いています。
当方、Mac Snow Leopard を使っているため、seq コマンドがデフォルトでは使えません。
そこで、.bashrc 内に、seq 関数をあらかじめ自分で定義して、他で使い回したいと思っています。
.bashrc の中に、
function seq() {
i=$1
while [ $i -le $2 ] ; do
echo $i
let i=$i+1
done
}
と、関数を定義しました。
seq 関数をターミナル上で実行すると、
>seq 0 2
0
1
2
と正しく、表示されます。次に、

#!/bin/sh
seq 0 2

...続きを読む

Aベストアンサー

追記

source は現在のシェルで実行し、結果がそのまま現在のシェルに適応されます。
今回の temp.sh なら
> source temp.sh

> seq 0 2
と入力したのと同等ということになります。

> ./temp.sh
この . はコマンドではなく、 temp.shへのパスを指定するものです。
実行ファイル名だけでコマンドとして実行できるのは、環境変数PATHで指定したディレクトリにあるものだけです。それ以外は、その実行ファイルへの絶対パス、または相対パスが必要となります。
これは、カレントディレクトリにある実行ファイルも例外ではありません。
環境変数PATHに . が無い場合は、 ./ファイル名 と相対パスを指定する必要があります。
(この点は、常に . がPATHにあるように振る舞うMS-DOSやコマンドプロンプトとは違います)
逆に、PATH上にあれば(例えば、 PATH=$HOME/bin:(以下略)となっている時の $HOME/bin )、 temp.sh とファイル名だけで実行できます。

また、こうしたコマンドは新規プロセスで実行されますので、環境変数を除いて、現在の設定は継承されません。
対話的ではないbashや、 shとして起動された bash は .bashrcを読まないので、そこに書いてあることは無効となります。

追記

source は現在のシェルで実行し、結果がそのまま現在のシェルに適応されます。
今回の temp.sh なら
> source temp.sh

> seq 0 2
と入力したのと同等ということになります。

> ./temp.sh
この . はコマンドではなく、 temp.shへのパスを指定するものです。
実行ファイル名だけでコマンドとして実行できるのは、環境変数PATHで指定したディレクトリにあるものだけです。それ以外は、その実行ファイルへの絶対パス、または相対パスが必要となります。
これは、カレントディレクトリにある実行...続きを読む

Q『存在するかどうか分からない』環境変数にcshで新しいパスを設定したい

Linuxを利用しており、「『存在するかどうか分からない』環境変数に新しいパスを設定したい」のですが、うまくいきません。
言い方を変えると、対象の環境変数が存在しようが存在しまいが、うまくいくようにしたいのです。

具体的には、ログインシェルに tcsh を使用しているため、hogehoge.cshを作成し、/etc/csh/login.d/に入れました。hogehoge.cshの内容は以下のようになります。

#!/bin/csh
setenv HOGEHOGEPATH /usr/lib/hogehoge:${HOGEHOGEPATH}

ログインしてみると
HOGEHOGEPATH: Undefined variable.
といった内容のエラーが表示され、環境変数も設定されません。

shで設定する方法もありますがcshで良い書き方はないでしょうか。ご教示お願いいたします。

Aベストアンサー

私の環境の/etc/profile.d/*.cshを参考にすると
============================================
#!/bin/csh
if ( $?HOGEHOGEPATH ) then
setenv HOGEHOGEPATH /usr/lib/hogehoge:${HOGEHOGEPATH}
else
setenv HOGEHOGEPATH /usr/lib/hogehoge
endif
============================================
のように変数が設定されている場合と
されていない場合を分岐させて書いてありました


人気Q&Aランキング