出産前後の痔にはご注意!

bashにてシェルスクリプトを作成しています。

XXXX_111122222333_YYYYMMDD
111122222333

といった2パターンのファイル名から、「111122222333」の部分を取得したいのですが、if文の条件式で悩んでいます。

if [ expr length ${p9} -gt 13 ]
then
a=`echo $p9|cut -c 6-9`
b=`echo $p9|cut -c 10-14`
c=`echo $p9|cut -c 15-18`
else
a=`echo $p9|cut -c 1-4`
b=`echo $p9|cut -c 5-9`
c=`echo $p9|cut -c 10-13`
fi

これで実行すると too many arguments というエラーが出てしまいます。(結果も正しくありません)
基本的な部分が理解できていないかと思うのですが、宜しくお願いいたします。

A 回答 (4件)

すみません、修正します。



> let len=`echo ${p9} | wc -c`-1

len=`echo -n ${p9} | wc -c`

の方が良いです。
    • good
    • 0
この回答へのお礼

ご丁寧にありがとうございました。

やはり expr はサポートされていなかったようで、教えていただいた方法で希望通りの処理を行うことが出来ました。

本当にありがとうございました。

お礼日時:2007/07/09 10:31

パターンの定義が不明ですが、


・取得したい値は、必ず「_(アンダーバー)」に挟まれている。
・「_(アンダーバー)」は、取得したい値の両端にあり、2つ以上存在しない。
・「_(アンダーバー)」が含まれていない場合は、評価する値は取得したい値そのものである。

であるならば、「_(アンダーバー)」をスペースに置き換えて、配列に入れてしまえば操作が楽だと思います。

◯パターン1
$ a=XXXX_111122222333_YYYYMMDD
$ b=( ${a//_/ }) aの内容で"_"を" "スペースに置き換えて、配列bに入れる
$ declare -p b 配列bの各要素の値を確認
declare -a b='([0]="XXXX" [1]="111122222333" [2]="YYYYMMDD")'
$ echo ${#b[@]} 配列bの要素の数
3
$ echo ${b[1]} 2番目の要素の表示
111122222333

◯パターン2
$ a=111122222333
$ b=( ${a//_/ })
$ echo ${#b[@]}
1
$ echo ${b[0]}
111122222333

評価したい値がどちらのパターンかは、配列の要素数で判断して、
b[1]かb[0]を最終的な値にすればいいですね。

あとは、スクリプトにするだけ。

・Bash 2.05以上で使えます。
・${変数名:オフセット:長さ}の形式で部分抽出することも出来そうですが、
複数回の評価が必要になるの・汎用的でない(数値の埋め込みが多くなる)ので、${変数名//パターン/置換文字列}にしました。
・外部コマンドを実行しないので(チョットだけ)早いです。

shスクリプトの書籍を紹介しておきます。
「シェルスクリプト基本リファレンス」[技術評論社](ISBN4-7741-2261-0)は、
shスクリプトの移植性に配慮された数少ない書籍で、shスクリプトを作り時には
手元に置いておきたい一冊だと思います。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

すごく丁寧にご説明いただいてありがとうございます。
勉強になりました。
紹介していただいた書籍、早速探してみたいと思います。

本当にありがとうございました。

お礼日時:2007/07/09 10:33

> expr: 構文エラー


expr --help や、expr --version を実行して、expr がサポートする書式やバージョンの確認をお願いします。expr length ??? をサポートしていない可能性もありますので。
もしサポートされていなければ、仕方がありませんから、

let len=`echo ${p9} | wc -c`-1

と言った代替手段を使うしかないでしょう。
    • good
    • 0

exprは使ったことが無かったのですが、if文の中に入れるとうまくいかないみたいです。

なので、処理を分けて、

len=`expr length ${p9}`

if [ $len -gt 13 ]
then
a=`echo $p9|cut -c 6-9`
b=`echo $p9|cut -c 10-14`
c=`echo $p9|cut -c 15-17`
else
a=`echo $p9|cut -c 1-4`
b=`echo $p9|cut -c 5-9`
c=`echo $p9|cut -c 10-12`
fi

の様に書けば宜しいかと。
    • good
    • 0
この回答へのお礼

ご回答いただきありがとうございます。

早速教えていただいた通りしてみたのですが、やはりエラーになります。

expr: 構文エラー

expr がなぜ構文エラーなのでしょうか??
manやネットで調べてみたのですが、そのような記述は見当たりません。
ご存知でしたら教えていただけますでしょうか?
お手数をお掛けします。。

お礼日時:2007/07/06 16:43

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

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

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

Qシェルスクリプトでファイル内の数値文字列を数値として扱うには

失礼します。
シェルスクリプトでファイル内のテキスト(数値文字列)を取得して、それを使って計算するにはどうすれば良いでしょうか?

str:ファイル内のテキスト(数値文字列)

res=$(( $str + 1 ))

・エラー
")syntax error: invalid arithmetic operator (error token is "


よろしくお願いします。

Aベストアンサー

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをexprに書き換えたところ
$ ./test2.sh
Using expr
09:19:00.302748000
09:19:19.259990000

exprだと19秒ですが、$(( 演算 )) だと10秒程度なので、演算が多くなれば確かにexprは不利ですね。

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをe...続きを読む

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

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

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

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

Aベストアンサー

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

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


人気Q&Aランキング