トップページunix
988コメント297KB

シェルスクリプト総合 その24©5ch.net

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。 転載ダメ©2ch.net2014/11/11(火) 00:54:03.43
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
 FreeBSDユーザは/bin/shの正体がashなので注意。
 v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
  http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
  http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
 (理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆーな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
 「そういうのはperl使いましょう」と回答するのはやめましょう。
 安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その23
http://peace.2ch.net/test/read.cgi/unix/1404204950/
0428名無しさん@お腹いっぱい。2015/03/13(金) 11:04:35.04
順序数?
0429名無しさん@お腹いっぱい。2015/03/13(金) 13:12:27.06
行番号を行数と呼ぶ人がいるとして、その人は行数を何と呼ぶのでしょうかね。行の数?
0430名無しさん@お腹いっぱい。2015/03/13(金) 17:11:36.57
行回数
0431名無しさん@お腹いっぱい。2015/03/14(土) 01:06:12.05
行数はnumber of linesだろ
Fランもたいがいにせいよ
0432名無しさん@お腹いっぱい。2015/03/14(土) 02:26:16.92
>>410
まあgrepでいいと思う

grep -n regexp FILE | tail -n1 | cut -d: -f1
awk /regexp/'{print NR}' FILE | tail -n1
sed -n /regexp/= FILE | tail -n1
0433名無しさん@お腹いっぱい。2015/03/14(土) 04:57:44.74
>>431
行数は line count (だからこそ grep -c )
0434名無しさん@お腹いっぱい。2015/03/14(土) 05:17:25.87
count number of lines じゃね
てかどーでもいいよ
行数にしろ行番号にしろ質問者が具体例を明示してる時点で誤解しようがないだろ
早がってんしたエスパースキルゼロのうっかりさんが
早漏の言い訳をぐだぐだぐだぐだぐだぐだぐだぐだぐだぐだ
くだらねー
0435名無しさん@お腹いっぱい。2015/03/14(土) 05:44:10.73
それは「行数を数えろ」だろ
中卒もたいがいにしとけ
0436名無しさん@お腹いっぱい。2015/03/14(土) 07:03:54.77
>>435
countは動詞だけじゃなく名詞にもなるんだよ、知らなかった?
0437名無しさん@お腹いっぱい。2015/03/14(土) 08:50:28.21
へー
0438名無しさん@お腹いっぱい。2015/03/14(土) 18:41:01.09
>>436
名詞が連続してるが、それはどう言い訳するんだ?
0439名無しさん@お腹いっぱい。2015/03/14(土) 21:16:03.47
http://www.gnu.org/software/grep/manual/grep.html#General-Output-Control
-c
--count
Suppress normal output; instead print a count of matching lines for each input file. With the -v (--invert-match) option, count non-matching lines. (-c is specified by POSIX.)
0440名無しさん@お腹いっぱい。2015/03/15(日) 00:27:31.56
一行の中に、
bbbbaaa124iiiiiccccaaaa456lllllddddaaa789と書いてあった場合に、
特定の文字列の後に続いている数字を、スペース空けて抜き出す書き方はないでしょうか
うえの場合だとaaaの後にあるものを抜き出すように、124 456 789のような・・
素人質問ですいませんがよろしくお願いします
0441名無しさん@お腹いっぱい。2015/03/15(日) 01:12:54.15
GNU grep が使えるなら

$ echo "bbbbaaa124iiiiiccccaaaa456lllllddddaaa789" | grep -Po '(?!aaa)[[:digit:]]+' | tr '\n' ' '
0442名無しさん@お腹いっぱい。2015/03/15(日) 02:09:05.45
>>441
できました!
使わせていただきます。ご親切にありがとうございました。
0443名無しさん@お腹いっぱい。2015/03/15(日) 03:20:18.84
追加で質問したいのですが、
上の例でbbbbaaa124iiiiicccc222aaaa456lllllddddaaa789とあった場合に、
aaaの直後でない222は省いて124 456 789だけ方法はないでしょうか
何度もすいません
0444名無しさん@お腹いっぱい。2015/03/15(日) 03:27:09.47
grep -Po '(?<=aaa)\d+'
0445名無しさん@お腹いっぱい。2015/03/15(日) 03:50:51.90
>>444
完璧にできました!
この時間に回答いただけるとは思いませんでした。
大変助かりました。ありがとうございました。
0446名無しさん@お腹いっぱい。2015/03/15(日) 13:29:40.91
何度もすいません
上の例で、bbbbaaa0.24iiiiicccc2.22aaaa456lllllddddaaa7.89 など
小数点も含む数字が混じっている場合に、同様の条件で0.24 456 7.9を抜き出す方法はないでしょうか
あまりにも聞きすぎなので最後にしようと思います。
0447名無しさん@お腹いっぱい。2015/03/15(日) 14:11:57.45
こうかなぁ…

grep -Po '(?<=aaa)\d+(\.\d+)?

でもこれだと、".01" とかにはマッチしないけどね。
それと、"1.2.3" なんて文字列があると、"1.2" にマッチしちゃう。
0448名無しさん@お腹いっぱい。2015/03/15(日) 14:12:54.78
ちったぁ自分で考えな
過去2回の答えがなぜそうなるのかを考えれば応用でいけるはずだ
0449名無しさん@お腹いっぱい。2015/03/15(日) 14:15:07.46
grep -o 'aaa[0-9\.][0-9\.]' | tr '\n' ' '
0450名無しさん@お腹いっぱい。2015/03/15(日) 14:16:19.36
ミス
grep -o 'aaa[0-9\.][0-9\.]*' | sed 's/aaa//g' | tr '\n' ' '
0451名無しさん@お腹いっぱい。2015/03/15(日) 14:37:30.13
>>447

grep -Po '(?<=aaa)\d+(\.\d+)?(?=[^\d.]|$)'
0452名無しさん@お腹いっぱい。2015/03/15(日) 14:52:31.67
>>447
>>449
>>450
再度ありがとうございました。
私のファイルのケースですと450さんのやり方で完全にできました!
大変助かりましたし、勉強になりました。ありがとうございました。


>>448
本当そうしようと思います。
それ以前にgrepやsedは簡単な文字抜き出しぐらいにしか使ったことがなかったのですが、
こんなに便利だとは驚きました。学習して次は自分で解決できるようにしたいと思います
04534482015/03/15(日) 14:55:28.70
これは私見だが
grepの-PはPerlの正規表現として扱うためのオプションだ
Perlを知ってるなら問題ないが、知らないなら>>450のが多分勉強対象としては正しい
0454名無しさん@お腹いっぱい。2015/03/15(日) 15:09:05.03
>>451
投稿した後でレス確認しました。すいません。
こちらのやり方でもできました!ありがとうございました。
書き方の意味を勉強してみたいと思います。
>>453
ありがとうございます。perlも知らないので、
教えていただいたオプションの意味も含めて調べてみようと思います。
0455名無しさん@お腹いっぱい。2015/03/25(水) 06:56:05.87
専用コマンド使わずに実用的な強度の暗号復号フィルタとか誰か書ける?
0456名無しさん@お腹いっぱい。2015/03/25(水) 12:51:41.84
>>455
専用コマンドってのは、gpg とか openssl みたいなのを指してるの?
python とか perl とかを使っていいのならライブラリ次第で何とでもなりそうだけど、
それも NG なのかな?
0457名無しさん@お腹いっぱい。2015/03/25(水) 15:07:14.94
rot13でよければ
tr A-Za-z N-ZA-Mn-za-m
0458名無しさん@お腹いっぱい。2015/03/25(水) 18:11:12.12
それはさすがに「実用的な強度」とは言えないのでは……
0459名無しさん@お腹いっぱい。2015/03/27(金) 22:26:36.44
会社でシェルスクリプト(awkやsed)いじる必要があるんですが
何かおすすめの本ないですか?
0460名無しさん@お腹いっぱい。2015/03/28(土) 00:47:40.73
ttp://www.goggle.co.jp/
0461名無しさん@お腹いっぱい。2015/03/28(土) 11:31:55.66
後ろからn文字目のみを削除する方法ってある?

1234567890
なら
123456780

12345
なら
1235

になるような。
0462名無しさん@お腹いっぱい。2015/03/28(土) 14:36:27.39
sed -e 's/.\(.\{n-1\}\)$/\1/'
後ろから2文字目なら
echo 12345 | sed -e 's/.\(.\{1\}\)$/\1/'
1235
0463名無しさん@お腹いっぱい。2015/03/28(土) 15:15:24.11
>>456
LL言語呼び出すにしても拡張ライブラリの専用コマンドに依存するのはNGじゃない?
nkfでrot13読むのは専用コマンドとは言えない気がするけど>>458だよなあ。

バイナリ法辺りを実装すればとりあえずなんとかなるんだろうか?
0464名無しさん@お腹いっぱい。2015/03/28(土) 15:18:54.26
>>461
rev, cut -c, head -c, tail -c などでいけるのでは?
$ echo 12345 | rev | cut -c1,3- | rev
1235
$ echo 1234567890 | rev | cut -c1,3- | rev
123456780
0465名無しさん@お腹いっぱい。2015/03/29(日) 05:16:26.01
>>461
>後ろからn文字目のみを削除する方法ってある?

a=1234567890; echo "${a%??}${a#?????????}"
0466名無しさん@お腹いっぱい。2015/03/29(日) 08:10:35.43
>>465
それ、n文字目と言うのが $n 変数に入ってる場合のこと聞いてるんでは? 固定数値ならいろいろ方法あるよ。
0467名無しさん@お腹いっぱい。2015/03/29(日) 13:30:23.41
>>466
可変でも同じことはできるけど。

a=1234567890; n=4; f(){ r=$1; while [ ${#r} != $2 ]; do eval r=\${r$3?}; done; echo $r; }; echo $(f $a $((${#a} - $n)) %)$(f $a $(($n - 1)) \#);
0468名無しさん@お腹いっぱい。2015/03/29(日) 13:51:13.01
もっとエレガントな方法がいいなぁ
0469名無しさん@お腹いっぱい。2015/03/29(日) 14:10:10.11
467が他の回答に勝っている点って何があるのかなあ
0470名無しさん@お腹いっぱい。2015/03/29(日) 14:39:04.14
bash + GNU coreutils の cut コマンド限定
範囲チェックはしていない

ncut () {
declare str="$1"
declare -i idx="$2"
declare -i len=$(expr length "$str")
echo $str | cut --complement -b$((len - idx + 1))
}

$ ncut 1234567890 2
123456780

$ ncut 12345 2
ncut 12345 2
0471名無しさん@お腹いっぱい。2015/03/29(日) 14:40:32.78
>>470
おっと、s/delcare/local/ でお願い
0472名無しさん@お腹いっぱい。2015/04/06(月) 20:37:17.61
$ N=1; echo 1234567890 | rev | sed 's/\(.\{'"$((N-1))"'\}\)./\1/' | rev
0473名無しさん@お腹いっぱい。2015/04/06(月) 23:05:32.98
xyzあいうえおabc
xyzかきくけこabc

というファイルがあったときに
あいうえお
かきくけこ
と抜き出す方法にはどうすればよいでしょうか
grepなどを使うとおもったのですがうまくいきません。
よろしければご教示おねがいします
0474名無しさん@お腹いっぱい。2015/04/07(火) 01:08:35.80
ファイル名変更じゃ無くて抜き出しなら
lsのオプション弄ってパイプでsedに繋げばいい

変更ならrename使おう
0475名無しさん@お腹いっぱい。2015/04/07(火) 01:19:37.06
sed 's/xyz\(.*\)abc/\1/g'
0476名無しさん@お腹いっぱい。2015/04/07(火) 23:44:39.59
例えば、
親ディレクトリ
/小ディレクトリA/photo/
/小ディレクトリB/photo/
/小ディレクトリC/photo/
みたいなディレクトリ構造があった時photo3つをpictureに
変更するにはどうすればよいのでしょうか
for文にmv入れ込めばできると思ったのですができませんでした
初歩的な質もう申し訳ありませんがよろしくお願いします。
0477名無しさん@お腹いっぱい。2015/04/07(火) 23:56:55.05
最後にスラッシュつけなきゃできると思うが
0478名無しさん@お腹いっぱい。2015/04/08(水) 00:23:18.58
for i in *; do cd $i; mv photo picture; done
なんとか自己解決しましたそして>>477有難う
0479名無しさん@お腹いっぱい。2015/04/08(水) 00:30:06.79
って違う
for i in *; do cd $i; mv photo picture; cd ..;done
こうだ!!一つしか変わってなかったぜ
0480名無しさん@お腹いっぱい。2015/04/08(水) 05:44:31.48
cdが無駄です。

for i in *; do mv "$i"/photo "$i"/picture; done

ディレクトリ名等にスペースが含まれていてもいいように $i は "$i" としておく。
0481名無しさん@お腹いっぱい。2015/04/09(木) 06:55:16.58
サブシェルとすればいいだけじゃね?
0482名無しさん@お腹いっぱい。2015/04/09(木) 08:37:12.98
サブシェルが無駄です。
0483名無しさん@お腹いっぱい。2015/04/09(木) 19:49:27.51
効率求めてshellなんか使っていない。
0484名無しさん@お腹いっぱい。2015/04/09(木) 22:21:14.40
その返しは馬鹿っぽいと思います
0485名無しさん@お腹いっぱい。2015/04/09(木) 23:52:38.50
>>476
http://x68000.q-e-d.net/~68user/unix/pickup?rename
util-linuxのrenameコマンドの場合
rename -v photo picture */photo

Debian系だと正規表現指定、できるかは不明
https://wiki.ubuntulinux.jp/UbuntuTips/FileHandling/RenameCommand

FreeBSDだとsysutils/renameで正規表現指定、できるかは不明
http://www.freshports.org/sysutils/rename/
0486名無しさん@お腹いっぱい。2015/04/15(水) 08:31:50.31
$> TIME="2015/04/15 08:25:16"

$> printf ${TIME:5:11}
04/15

$> echo ${TIME:5:11}
04/15 08:25

$> printf "${TIME:5:11}"
04/15 08:25

罠だ、はまった。。。
0487名無しさん@お腹いっぱい。2015/04/15(水) 08:45:36.46
何が罠なの?

シェル変数の展開時には " " でかこんで "${HOGE...}" にするのが基本。
0488名無しさん@お腹いっぱい。2015/04/15(水) 08:48:00.87
最初から、
date '+%m/%d %H:%M'
にした方がいいのでは?
0489名無しさん@お腹いっぱい。2015/04/15(水) 08:48:10.66
>>486
$ printf "${TIME:5:11}"
04/15 08:25

$ printf "%s %s\n" ${TIME:5:11}
04/15 08:25
0490名無しさん@お腹いっぱい。2015/04/15(水) 09:14:12.79
$ TIME="2015/04/15 08:25:16"
$ printf ${TIME:5:11}
04/15
$ /usr/bin/printf ${TIME:5:11}
04/15/usr/bin/printf: warning: ignoring excess arguments, starting with `08:25'
$ type printf
printf is a shell builtin
0491名無しさん@お腹いっぱい。2015/04/15(水) 13:25:09.88
$ TIME="2015/04/15 13:30:16"
$ printf ${TIME:5:11}
04/15

$ IFS="wanada"
$ printf ${TIME:5:11}
04/15 13:30
0492名無しさん@お腹いっぱい。2015/04/15(水) 13:48:45.04
bash依存をやめよう

$ TIME="2015/04/15 08:25:16"
$ printf ${TIME:5:11}
sh: Bad substitution

$ IFS='/ :'
$ set $TIME
$ echo $2/$3 $4:$5
04/15 08:25
0493名無しさん@お腹いっぱい。2015/04/16(木) 23:26:24.70
GNU date
$ TIME="2015/04/15 08:25:16"
$ date '+%m/%d %H:%M' --date="${TIME}"
04/15 08:25
0494名無しさん@お腹いっぱい。2015/04/30(木) 23:24:48.53
今月のsoftware designはgrepsedawk入門で面白かったな
0495名無しさん@お腹いっぱい。2015/05/07(木) 20:52:12.51
シェルスクリプトを最近使うようになりffmpegなどにファイルを投げて一括処理できるようになりました。
でも、エラー処理に困っています。例えば、ffmpegで作ったファイルが壊れているかどうかわからないのです。
ffmpegはファイルとログを出してくれるのでログの特定の文字(たとえば、bad header、skip)が出てきたときに、
その時のログを書き出し、そのログを使って処理を分岐させることは可能なのでしょうか?
このときffmpegは終了コードは0を返してきました。プログラムによっては終了コード1を返してしてくるものもありました。
0496名無しさん@お腹いっぱい。2015/05/07(木) 20:53:06.51
grep君でうまく抽出したら正規表現で検索すればできるのでは?
0497名無しさん@お腹いっぱい。2015/05/07(木) 21:54:28.34
>>495
ffmpegは最後に 2>&1 を付ける
付ければログをgrepとかできる
0498名無しさん@お腹いっぱい。2015/05/08(金) 20:35:13.72
grepをどう使えばいいのですか?
0499名無しさん@お腹いっぱい。2015/05/08(金) 22:13:16.56
manくらい見た?
0500名無しさん@お腹いっぱい。2015/05/08(金) 22:36:52.79
うーんこの
man見てくれよせめて--helpとかググるとかしろよ
0501名無しさん@お腹いっぱい。2015/05/09(土) 12:39:02.61
こんな感じでエラー処理するんだよ
書き込みの内容見てる限りは無理だと思うけど

ffmpeg xxxx > xxxx.log 2>&1

cat xxxx.log | grep "bad header"

if [ $? -ne 0 ]
then
# エラー処理
fi
0502名無しさん@お腹いっぱい。2015/05/09(土) 12:42:06.41
catは無駄だな。
0503名無しさん@お腹いっぱい。2015/05/09(土) 13:01:23.55
if [ も無駄だな
0504名無しさん@お腹いっぱい。2015/05/09(土) 13:11:39.85
>>502
判定が1種類だと思ってるアホ発見
0505名無しさん@お腹いっぱい。2015/05/09(土) 13:25:48.27
>>504
二種類あるとどうなるわけ?w
0506名無しさん@お腹いっぱい。2015/05/09(土) 13:26:22.67
無駄だなw
0507名無しさん@お腹いっぱい。2015/05/09(土) 13:32:28.84
>>504
わかった、こいつ馬鹿だから、catがどう無駄なのかわかってないんだ。
なるほどなー、馬鹿だなーw
0508名無しさん@お腹いっぱい。2015/05/09(土) 15:56:32.15
ffmpeg xxxx > xxxx.log 2>&1

if ! grep "bad header" <xxxx.log
then
# エラー処理
fi
0509名無しさん@お腹いっぱい。2015/05/09(土) 18:51:16.11
if [ -n "$(grep 'bad header' xxxx.log)" ]; then
fi
0510名無しさん@お腹いっぱい。2015/05/09(土) 20:08:36.31
grep -qs "bad header" xxxx.log
case $? in 0) echo "Match";; 1) echo "No match";; *) echo "Error";; esac
0511名無しさん@お腹いっぱい。2015/05/11(月) 21:15:37.13
>>508
これだと判定のたびにログを全部読み直すから無駄無駄
0512名無しさん@お腹いっぱい。2015/05/11(月) 22:56:21.16
>>511
どう直せばいいと思う?
0513名無しさん@お腹いっぱい。2015/05/12(火) 18:27:59.13
bashで
for i in $@
do
command
echo ○○中××番目を処理中です。
done
としたいのですが、○○と××はどうすれば表示できるようになりますか?
0514名無しさん@お腹いっぱい。2015/05/12(火) 19:54:49.92
もう一つ聞きたいことがありました
for i in $@にカレントディレクトリだけじゃなく
そのサブディレクトリのファイルを送るにはどう書けばよいのですか?
0515名無しさん@お腹いっぱい。2015/05/12(火) 19:59:27.57
>>513
count=1
for i in $@
do
echo "$#中${count}番目を処理中です。"
command
count=$(($count + 1))
done
0516名無しさん@お腹いっぱい。2015/05/12(火) 20:00:20.69
コピペから脱却すればその答えはおのずと見つかるであろう
0517名無しさん@お腹いっぱい。2015/05/12(火) 20:18:46.18
わざわざ指摘させる流れですか?もうひとつは残しておいた

in $@ は無駄だな
0518名無しさん@お腹いっぱい。2015/05/13(水) 06:35:40.84
$count の $ は無駄だな。
count=$(($count + 1)) の行自体も無駄とは言わないけどbashなら不要だな。

echo "$#中$(( count++ ))番目を処理中です。"
0519名無しさん@お腹いっぱい。2015/05/13(水) 07:02:23.50
>>518
可読性・保守性が悪いから却下
0520名無しさん@お腹いっぱい。2015/05/13(水) 07:23:59.83
for ((i=1;i<=$#;i++)); do echo "${#}中${i}番目を処理中"; done
0521名無しさん@お腹いっぱい。2015/05/13(水) 07:39:14.30
>>520
それだと肝心の $@ の処理ができないじゃん、本末転倒。
0522名無しさん@お腹いっぱい。2015/05/13(水) 08:39:25.96
$@ をどう処理したいの? 例えばこんな感じ?

for ((i=1;i<=$#;i++)); do eval item=\${$i};echo "${#}中${i}番目($item)を処理中"; done
0523名無しさん@お腹いっぱい。2015/05/13(水) 13:58:41.25
curlでメールチェックできないかと思ったんだけど、どうも参考コードが見当たらないなあ。
もしかしてtelnetのような感じの方法になってスマートには無理なのだろうか?
0524名無しさん@お腹いっぱい。2015/05/13(水) 17:11:23.00
こういうことではなくて?

http://blog.sarabande.jp/post/88910085203
0525名無しさん@お腹いっぱい。2015/05/13(水) 17:26:02.42
送信と受信の違いがわからない男おことわりw
0526名無しさん@お腹いっぱい。2015/05/13(水) 17:49:35.48
ああなるほど、送信がわかれば受信もできるのがわかるから
調べればいいのにと思ったのに
実装されてるコードそのものが欲しかったのね
キミのレベルに合わせられなくてごめんね
0527名無しさん@お腹いっぱい。2015/05/13(水) 17:52:16.16
マニュアル見れば受信できることなんて一目瞭然だよ
0528名無しさん@お腹いっぱい。2015/05/13(水) 19:45:16.01
カウントありがとうございます
サブディレクトリのほうは無理のでしょうか?
■ このスレッドは過去ログ倉庫に格納されています