シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)もしくはPOSIX準拠の互換シェルがデフォルトです。
bash/zsh/ksh/ash/dash/yash/poshなどの専用機能に依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
FreeBSDユーザは/bin/shの正体がashなので注意。
・POSIXについてのリンクは https://en.wikipedia.org/wiki/POSIX にまとめられています
最新の仕様はこちらへ http://pubs.opengroup.org/onlinepubs/9699919799/
(左上の「Shell & Utilities」 から参照することができます。)
・v7 shに一番近くて、現役(?)のshは、OpenSolaris由来のheirloom sh。
http://src.illumos.org/source/xref/illumos-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に逃げずにシェルスクリプトで処理するのが頭のいいやり方。
質問に対して問題が間違ってるといちゃもんをつけるのもやめましょう
シェルスクリプト総合 その27
https://mevius.5ch.net/test/read.cgi/unix/1525337663/
探検
シェルスクリプト総合 その28
■ このスレッドは過去ログ倉庫に格納されています
2018/08/02(木) 05:22:16.82
2021/05/22(土) 12:12:52.06
そもそもカーネルやシステム中核プロセスが不可視であるべき、ってのは常識なのか?
ディレクトリの閲覧権限はxとwで制限できるから、そりゃ隠れてるのも居るかもしれないけどさ
Macは使わないので分からんが、windowsだってタスクマネージャ開けばユーザー権限で干渉不可なシステムプロセスがゾロゾロ動いてるの見えるけど
ディレクトリの閲覧権限はxとwで制限できるから、そりゃ隠れてるのも居るかもしれないけどさ
Macは使わないので分からんが、windowsだってタスクマネージャ開けばユーザー権限で干渉不可なシステムプロセスがゾロゾロ動いてるの見えるけど
2021/05/22(土) 12:37:32.55
OpenBSDでは5.7からprocfsは削除された
https://www.openbsd.org/plus57.html
> Deleted procfs (always suffered from race conditions and is now unused).
procfsを削除しました(常に競合状態に悩まされ、現在は使用されていません)
https://www.openbsd.org/plus57.html
> Deleted procfs (always suffered from race conditions and is now unused).
procfsを削除しました(常に競合状態に悩まされ、現在は使用されていません)
2021/05/22(土) 12:40:36.82
UNIXの全てがファイルという考えは面白かったが
本当に全てがファイルであるというは正しい考えなのだろうか?
本当に全てがファイルであるというは正しい考えなのだろうか?
2021/05/22(土) 12:58:05.17
読み書き出来るならファイルと見做せるんじゃね
環境変数なんかは読み書きできるけどファイルじゃないね
cpuは一応procにcpuinfoあるけど、別にフルアクセスできるわけじゃなし形だけね
lsofやpsで情報が得られるが、lsでアクセスできないならファイルとして抽象化されていない、でいいのかな(procfsが無いならlsできない、でいいの?)
それならOSのレベルで抽象化しなくても、シェルのレベルでファイルシステムのように見せる事もできる
windowsがそうだ)
cmdの振る舞いを見るとOSレベルでの一貫性は皆無だけど、pwshからはプロセス、レジストリ、環境変数まで全部ファイルシステムとして読み書きできるわけで
環境変数なんかは読み書きできるけどファイルじゃないね
cpuは一応procにcpuinfoあるけど、別にフルアクセスできるわけじゃなし形だけね
lsofやpsで情報が得られるが、lsでアクセスできないならファイルとして抽象化されていない、でいいのかな(procfsが無いならlsできない、でいいの?)
それならOSのレベルで抽象化しなくても、シェルのレベルでファイルシステムのように見せる事もできる
windowsがそうだ)
cmdの振る舞いを見るとOSレベルでの一貫性は皆無だけど、pwshからはプロセス、レジストリ、環境変数まで全部ファイルシステムとして読み書きできるわけで
2021/05/22(土) 13:02:29.53
> (procfsが無いならlsできない、でいいの?)
無理やりlsで表示させるんじゃなくて
別の形のコマンドを作るべきじゃなかったのか?ということ
無理やりlsで表示させるんじゃなくて
別の形のコマンドを作るべきじゃなかったのか?ということ
2021/05/22(土) 15:40:34.99
>>408
race conditionって具体的に何だろ、デバイスファイルに読み書き競合、あるいは排他制御でブロッキング頻発か
event pollみたいな仕組みはlinux固有だっけ?
どう上手くやろうがfdのやりくりをする方式はスケーラブルじゃないと思ってる
多重I/Oでパフォーマンス向上とか言ってOSに過剰なfd要求コール送り続けてるんだから
race conditionって具体的に何だろ、デバイスファイルに読み書き競合、あるいは排他制御でブロッキング頻発か
event pollみたいな仕組みはlinux固有だっけ?
どう上手くやろうがfdのやりくりをする方式はスケーラブルじゃないと思ってる
多重I/Oでパフォーマンス向上とか言ってOSに過剰なfd要求コール送り続けてるんだから
2021/05/22(土) 17:08:31.51
>>412
たぶん情報を取得したが取得中にリアルタイムで情報が変わってしまい
矛盾した情報になってしまったとかじゃね?
もしくは複数のファイルから取得した情報が矛盾してしまうとか
情報を取得してからそれを利用するまでの間に時間があるから
取得した情報が信用できないというのは当然として少なくとも取得した時点では
それらの情報は矛盾しないようにスナップショットである必要がある
たぶん情報を取得したが取得中にリアルタイムで情報が変わってしまい
矛盾した情報になってしまったとかじゃね?
もしくは複数のファイルから取得した情報が矛盾してしまうとか
情報を取得してからそれを利用するまでの間に時間があるから
取得した情報が信用できないというのは当然として少なくとも取得した時点では
それらの情報は矛盾しないようにスナップショットである必要がある
2021/05/22(土) 22:12:21.51
例えば歯抜け連番名ファイルを詰めて連番にする場合
for f in renban* ; do
mv $f 新ファイル名
done
とやると、該当ファイルが0個でもループ内の mv を実行しようとしてエラーになります。
ループ前に該当ファイルの有無のチェックが不要な方法はないでしょうか?
for f in renban* ; do
mv $f 新ファイル名
done
とやると、該当ファイルが0個でもループ内の mv を実行しようとしてエラーになります。
ループ前に該当ファイルの有無のチェックが不要な方法はないでしょうか?
2021/05/22(土) 22:12:33.00
2021/05/22(土) 22:35:09.95
>>414
たぶんrenban*がfに入るってるよね
モダンなシェルならsetで好きな挙動選べるよ
(bashならnullglobとかglobfailとか)
ただ、わざわざその一文の為にオプションいじくるよりは普通にチェックした方がいいと思うよ
たまにおまじない書き忘れて頭ひねったりするから
たぶんrenban*がfに入るってるよね
モダンなシェルならsetで好きな挙動選べるよ
(bashならnullglobとかglobfailとか)
ただ、わざわざその一文の為にオプションいじくるよりは普通にチェックした方がいいと思うよ
たまにおまじない書き忘れて頭ひねったりするから
2021/05/23(日) 06:00:13.67
こんな感じかなあ?
set -- renban*
[ $# -eq 1 ] && [ ! -e "$1" ] && set --
for f in "$@"; do
mv $f 新ファイル名
done
でもまあ、ファイル名一覧を取得してからmvしてる間に
ファイルが別プロセスによって消されてリすることがあるから
どちらにしろmvがエラーになる可能性はあるんだよね
set -- renban*
[ $# -eq 1 ] && [ ! -e "$1" ] && set --
for f in "$@"; do
mv $f 新ファイル名
done
でもまあ、ファイル名一覧を取得してからmvしてる間に
ファイルが別プロセスによって消されてリすることがあるから
どちらにしろmvがエラーになる可能性はあるんだよね
2021/05/23(日) 10:42:49.61
ls renban* | while read f;do mv $f 新ファイル名; done
だとループには入らないけど、ファイルがないときにlsがエラー吐くねw
find -maxdepth 1 -name "*.csv" | while read f;mv $f 新ファイル名;done
これでどう?w
> ファイルが別プロセスによって消されてリすることがあるから
↑もちろんこの問題は避けられないけどね。
だとループには入らないけど、ファイルがないときにlsがエラー吐くねw
find -maxdepth 1 -name "*.csv" | while read f;mv $f 新ファイル名;done
これでどう?w
> ファイルが別プロセスによって消されてリすることがあるから
↑もちろんこの問題は避けられないけどね。
2021/05/23(日) 10:45:47.34
どうせワンタイムだろうしあんまり細かいこと気にしてるとハゲるぞー
といいつつ
もしrenbanが何万にものぼるとして、globしてからmvに取り掛かるまでの時間差が気になるんだったら
findに-name 'renban*'を処理させ、アクションの逐次実行を指定する;を渡せば隙は(ほぼ)ないはず
-exec {} target$suffix \;
+を渡すと速いけどバッチ処理だからglobとおんなじ
といいつつ
もしrenbanが何万にものぼるとして、globしてからmvに取り掛かるまでの時間差が気になるんだったら
findに-name 'renban*'を処理させ、アクションの逐次実行を指定する;を渡せば隙は(ほぼ)ないはず
-exec {} target$suffix \;
+を渡すと速いけどバッチ処理だからglobとおんなじ
2021/05/23(日) 10:55:53.30
>>419
find -maxdepth 1 -name "renban*" -exec mv {} 新ファイル名 \;
かw
そうだね、それが正解だw
(なんでもパイプで渡してしまう悪いくせを晒してしまった…w)
find -maxdepth 1 -name "renban*" -exec mv {} 新ファイル名 \;
かw
そうだね、それが正解だw
(なんでもパイプで渡してしまう悪いくせを晒してしまった…w)
2021/05/23(日) 10:57:03.17
>>418
スルーしてほしいってのが要望のようだけど、対象指定をミスったなら失敗する方が健全だと思います
スルーしてほしいってのが要望のようだけど、対象指定をミスったなら失敗する方が健全だと思います
2021/05/23(日) 11:15:08.17
>>421
まあ、依頼主の要望を可能な限り叶えたまでさ。
あとは好みと状況でどちらでもお好きな方をw
ただ、この場合lsでやっつけてるけど、本当はlsの出力はそんなにあてにして
いいものではないので、気をつけて。
いろんな意味でfind -execの方が正統だよ。
まあ、依頼主の要望を可能な限り叶えたまでさ。
あとは好みと状況でどちらでもお好きな方をw
ただ、この場合lsでやっつけてるけど、本当はlsの出力はそんなにあてにして
いいものではないので、気をつけて。
いろんな意味でfind -execの方が正統だよ。
423419
2021/05/23(日) 12:19:18.50 shのglobはソート済みが保証されてたと思うけど、findはどうだったか自信がない…
誰か試せる人補足よろしく
誰か試せる人補足よろしく
2021/05/23(日) 13:00:38.86
ソートしてから逐次実行してるんなら期待してたアトミック性は無いねー
2021/05/23(日) 13:14:58.68
>>423
findはディスクに忠実にファイルシステム上の順番だね。
そして、globは確かにソートされてるようだ。
ちなみにlsもソートされるし、それはオプションで変えられる、と。
一応、環境書いとくと、Fedora33のbashにて
findはディスクに忠実にファイルシステム上の順番だね。
そして、globは確かにソートされてるようだ。
ちなみにlsもソートされるし、それはオプションで変えられる、と。
一応、環境書いとくと、Fedora33のbashにて
2021/05/23(日) 13:36:53.66
2021/05/23(日) 13:40:34.27
globかlsのたypoです
2021/05/24(月) 02:05:05.30
414です
回答ありがとうございます。
ループ前チェックは何だか美しくないように思えたので(個人の感想です)
0個なら即doneに移る方法はないものかとお尋ねした次第です。
0個でも一度はループに入るという仕様が続いているのはきっと何か意味があるのでしょうね。
回答ありがとうございます。
ループ前チェックは何だか美しくないように思えたので(個人の感想です)
0個なら即doneに移る方法はないものかとお尋ねした次第です。
0個でも一度はループに入るという仕様が続いているのはきっと何か意味があるのでしょうね。
2021/05/24(月) 08:05:21.35
ループじゃなくて*の展開の仕様だよ
合理的に考えれば、展開を指示してマッチ無しならば0件にヒットしたとして何も返さないか空文字
展開が失敗したと考えてエラーのどちらかだろう
多分深い意味はないから気にすんな
合理的に考えれば、展開を指示してマッチ無しならば0件にヒットしたとして何も返さないか空文字
展開が失敗したと考えてエラーのどちらかだろう
多分深い意味はないから気にすんな
2021/05/24(月) 08:08:28.58
いや気にしなきゃだめか
ココがヘンだよbshくらいの気持ちで構えてれば、案外可愛く思えてくるぞ
ココがヘンだよbshくらいの気持ちで構えてれば、案外可愛く思えてくるぞ
431名無しさん@お腹いっぱい。
2021/05/24(月) 09:50:48.812021/05/24(月) 10:20:26.93
lsとglobがソートされるってどこに書いてあったっけ?
前に見た気がするけど英語の中から探すのめんどいw
前に見た気がするけど英語の中から探すのめんどいw
2021/05/24(月) 10:48:30.44
globで見つからなかった時、検索した文字列を返すのは
おそらく安全側に倒したからだと思ってるんだがいい例が思いつかないな
例えばcmd renban* hoge.tar.gzだったら普通は引数が2個以上になると思うが
見つからない時cmd hoge.tar.gzとなって危険とか
もしくはエラーメッセージをわかりやすく出すのが目的だったりするのかな?
空ディレクトリでls renban*を実行した時
「renban*」という文字列を返せば、エラーメッセージは分かりやすい
> ls: 'renban*' にアクセスできません: そのようなファイルやディレクトリはありません
空文字を返せば、エラーメッセージは分かりにくい
> ls: '' にアクセスできません: そのようなファイルやディレクトリはありません
何も返さなければ、何も表示せず正常終了
・・・あ、これかw
空ディレクトリでない(file1 file2 file3というファイルが有る)場合renban*が
何も返さないとlsが実行されるからfile1 file2 file3と表示されるんだ
renbanなんたらを処理しようとしてるのに、関係ないファイルを処理してしまう。
おそらく安全側に倒したからだと思ってるんだがいい例が思いつかないな
例えばcmd renban* hoge.tar.gzだったら普通は引数が2個以上になると思うが
見つからない時cmd hoge.tar.gzとなって危険とか
もしくはエラーメッセージをわかりやすく出すのが目的だったりするのかな?
空ディレクトリでls renban*を実行した時
「renban*」という文字列を返せば、エラーメッセージは分かりやすい
> ls: 'renban*' にアクセスできません: そのようなファイルやディレクトリはありません
空文字を返せば、エラーメッセージは分かりにくい
> ls: '' にアクセスできません: そのようなファイルやディレクトリはありません
何も返さなければ、何も表示せず正常終了
・・・あ、これかw
空ディレクトリでない(file1 file2 file3というファイルが有る)場合renban*が
何も返さないとlsが実行されるからfile1 file2 file3と表示されるんだ
renbanなんたらを処理しようとしてるのに、関係ないファイルを処理してしまう。
2021/05/24(月) 20:33:55.32
一つでもあればループ内を実行して、(それ以上)無ければ抜ける。
だから、(最初から)無ければそのまま抜けて欲しいな、と。
該当するものが無いのだからループ内を実行するのは無意味だし。
だから、(最初から)無ければそのまま抜けて欲しいな、と。
該当するものが無いのだからループ内を実行するのは無意味だし。
435名無しさん@お腹いっぱい。
2021/06/06(日) 22:14:34.25 標準出力の速度を制限したり、通信速度を表示するコマンドを探しています。どなたか知りませんか?
2021/06/07(月) 00:11:53.58
>>435
pvコマンド(Pipe Viewer)でどうよ
pvコマンド(Pipe Viewer)でどうよ
437名無しさん@お腹いっぱい。
2021/06/07(月) 11:25:09.09438名無しさん@お腹いっぱい。
2021/06/15(火) 00:01:20.06 sed の 's/foo/bar/'
スラッシュ直前の【s】って何の意味でしょうか?
g:global
i:ignore
のような意味ありますか?
またman以外でこのような略語を調べるサイトなどありますでしょうか?
スラッシュ直前の【s】って何の意味でしょうか?
g:global
i:ignore
のような意味ありますか?
またman以外でこのような略語を調べるサイトなどありますでしょうか?
2021/06/15(火) 00:58:11.44
440名無しさん@お腹いっぱい。
2021/06/15(火) 01:15:20.43 >>439
ありがとうございます
ありがとうございます
2021/06/15(火) 11:14:03.04
edコマンドで気になってるのはv
versed subst?
でもversedって多分古語だしなあ…
exec grep -v "$@"にvrepと名付けることにした
versed subst?
でもversedって多分古語だしなあ…
exec grep -v "$@"にvrepと名付けることにした
2021/06/15(火) 15:03:29.77
>>441
grep の -v は --invert-match だから inVert substitute じゃねーの?
grep の -v は --invert-match だから inVert substitute じゃねーの?
2021/07/28(水) 19:08:57.09
_数字列_数字列_数字列_を含む文字列から先頭の数字列だけを取り出したいので
前段階としてそれより前の部分を切り出すために
echo ${文字列%_*[0-9]_*[0-9]_*[0-9]_*}
としてみたのですが、
aaa_bbb_ccc_ddd_eee_123_4_567_xxxxx_123yyy_4f6_789c_zzz
の場合には aaa_bbb_ccc_ddd_eee ではなく aaa_bbb_ccc_ddd_eee_123 になってしまいます。
どうすればいいでしょうか?
前段階としてそれより前の部分を切り出すために
echo ${文字列%_*[0-9]_*[0-9]_*[0-9]_*}
としてみたのですが、
aaa_bbb_ccc_ddd_eee_123_4_567_xxxxx_123yyy_4f6_789c_zzz
の場合には aaa_bbb_ccc_ddd_eee ではなく aaa_bbb_ccc_ddd_eee_123 になってしまいます。
どうすればいいでしょうか?
2021/07/28(水) 19:47:08.66
どう言った用途に使うんでしょうかね
2021/07/28(水) 21:32:13.47
446名無しさん@お腹いっぱい。
2021/07/30(金) 07:50:18.18 >>443
そうなるように書いていますけど?
そうなるように書いていますけど?
447名無しさん@お腹いっぱい。
2021/07/30(金) 07:51:44.84 彼はsubstringの概念がないんでしょうかね。
2021/07/30(金) 08:39:43.50
任意個数の数字だけの塊をglobは表現できないので、お題の変換は無理
2021/08/08(日) 22:00:16.40
書き込めるかテスト
2021/08/08(日) 22:07:53.75
>>443
こんな感じでいけるんでね?前段階の話すっ飛ばして答えだけど
テストしてないので動かなくても知らん
isnum() {
case "$1" in
*[!0-9]*) return 1 ;;
*) return 0 ;;
esac
}
str="aaa_bbb_ccc_ddd_eee_123_4_567_xxxxx_123yyy_4f6_789c_zzz"
IFS="_"
set -- $str
while [ "$#" -gt 0 ]; do
if isnum "$1" && isnum "$2" && isnum "$3"; then
echo "$1"
fi
shift
done
こんな感じでいけるんでね?前段階の話すっ飛ばして答えだけど
テストしてないので動かなくても知らん
isnum() {
case "$1" in
*[!0-9]*) return 1 ;;
*) return 0 ;;
esac
}
str="aaa_bbb_ccc_ddd_eee_123_4_567_xxxxx_123yyy_4f6_789c_zzz"
IFS="_"
set -- $str
while [ "$#" -gt 0 ]; do
if isnum "$1" && isnum "$2" && isnum "$3"; then
echo "$1"
fi
shift
done
2021/08/08(日) 22:24:57.80
>>445のいうように、sedで一行それも大したことない正規表現で済むな
シェルスクリプトだけという課題の制限でもなければ
シェルスクリプトだけという課題の制限でもなければ
2021/08/09(月) 01:15:27.49
シェルスクリプトで無理といった途端
シェルスクリプトの実装が出てきたんで
慌てて取り繕ったか?w
シェルスクリプトの実装が出てきたんで
慌てて取り繕ったか?w
2021/08/09(月) 01:42:06.59
ねじ曲がりすぎ
そんな発想になるのは、お前>>450ぽいな
そんな発想になるのは、お前>>450ぽいな
2021/08/09(月) 13:03:23.04
俺は面白いと思うぞ、やりたくないけどな
bashやzshならパターンの否定が使えるextglobオプション+%パラメータ展開を使うのが多分一番楽かと
bashやzshならパターンの否定が使えるextglobオプション+%パラメータ展開を使うのが多分一番楽かと
2021/08/18(水) 19:41:40.78
藤林丈司
2021/08/31(火) 05:29:27.62
引数を表示するのに
echo $1
だけのスクリプトファイルを作って実行するのですが
なぜか引数が1&2等の場合にうまくいきません
echo $1
だけのスクリプトファイルを作って実行するのですが
なぜか引数が1&2等の場合にうまくいきません
2021/08/31(火) 05:46:42.81
そうなんですね
2021/08/31(火) 11:29:04.37
標準出力とエラー出力を引数にしたいってことループしないそれ
2021/08/31(火) 11:54:53.66
2021/08/31(火) 12:07:22.10
単に
sh scriptfile.sh 1&2
ってやってしまってるだけじゃないの
呼び出す側の問題
echoで展開後に&が問題になることはないのでクォートしなくても問題にはならない。クォートした方がいいけど
sh scriptfile.sh 1&2
ってやってしまってるだけじゃないの
呼び出す側の問題
echoで展開後に&が問題になることはないのでクォートしなくても問題にはならない。クォートした方がいいけど
2021/09/01(水) 00:03:03.07
2021/09/01(水) 02:30:08.96
そんなわかりきったことを
マウントとりたがりすぎ
マウントとりたがりすぎ
2021/09/01(水) 03:42:36.41
2021/09/01(水) 11:21:33.57
間違った指摘してたくせにw
何で常時偉そうにしなきゃならんのだかだが、自覚ないアホか
何で常時偉そうにしなきゃならんのだかだが、自覚ないアホか
2021/09/02(木) 16:02:37.40
コマンド展開で質問。
echo $(...) | sed ...
みたいなスクリプトで、$(...)内のコマンドが失敗したとき、そこでエラー終了してほしいんだけど、ムリ?
set -eしても、これには効果がないもよう。
echo $(...) | sed ...
みたいなスクリプトで、$(...)内のコマンドが失敗したとき、そこでエラー終了してほしいんだけど、ムリ?
set -eしても、これには効果がないもよう。
2021/09/02(木) 17:36:39.83
コマンド置換ではムリだねえ
2021/09/02(木) 17:47:03.78
>コマンド置換ではムリだねえ
コマンドの引数にあるのはね
コマンド置換でも変数に入れるだけなら終了ステータス返る/見れる=-eなら止まる。そっちはやってるとかあるだろうけど、いちおう
コマンドの引数にあるのはね
コマンド置換でも変数に入れるだけなら終了ステータス返る/見れる=-eなら止まる。そっちはやってるとかあるだろうけど、いちおう
2021/09/03(金) 12:16:10.43
え?馬鹿なの?
var=$(...)
echo "$var" | sed ...
ってするだけじゃん
var=$(...)
echo "$var" | sed ...
ってするだけじゃん
2021/09/03(金) 12:25:07.03
すでにそう書かれてるだろうに
2021/09/03(金) 12:30:46.29
流れとか関係なくどこまで知っているのか想定もせず、
偉ぶれると思ったら食いつくいつもの馬鹿だろな
偉ぶれると思ったら食いつくいつもの馬鹿だろな
2021/09/03(金) 12:47:59.60
口は悪いけどみんなと仲良くしたいだけなんです大目に見てあげてください
2021/09/03(金) 12:51:54.14
>>470
おまえこそ、いつものマウンターマウンターだな。w
おまえこそ、いつものマウンターマウンターだな。w
2021/09/03(金) 13:51:00.00
>>471
そうでもないそうではないようだけどw
そうでもないそうではないようだけどw
2021/09/03(金) 15:15:28.44
2021/09/04(土) 07:46:40.91
だからさ、もう結論出てるんだよ
var=$(...)
echo "$var" | sed ...
こう書けば終わり
var=$(...)
echo "$var" | sed ...
こう書けば終わり
2021/09/05(日) 01:55:02.26
きも
2021/09/08(水) 16:22:00.10
sedのホールドスペースは、その内容を削除するにはどうすれば?
とりあえずs/.//g;xでできたけど、もっと直接的なやりかたはないんかなー、と。
とりあえずs/.//g;xでできたけど、もっと直接的なやりかたはないんかなー、と。
2021/09/08(水) 16:43:31.22
2021/09/08(水) 17:50:14.30
おう
2021/09/27(月) 09:26:46.66
怪しげなシェル芸が宣伝中
【広告記事】今、ユニケージ開発手法にギークが熱狂するワケ【USP研究所代表&オープンソースOSコミッター対談】
ttps://type.jp/et/feature/14070/
【広告記事】今、ユニケージ開発手法にギークが熱狂するワケ【USP研究所代表&オープンソースOSコミッター対談】
ttps://type.jp/et/feature/14070/
2021/11/03(水) 02:25:59.11
空白行でいくつかのブロックに分割されたテキストにて、
文字列にマッチするブロックを出力する方法を探してます
たとえば
111
222
222
aaa
222
333
333
333
のようなテキスト中から、aaaを検索した際に、その前後の空白行に囲まれたブロックである
222
222
aaa
222
という結果を得たいです
いまは最初にブロックごとに一時ファイルを作り、それぞれに対してgrepにて検索し
マッチしたファイルを出力、としているのですがブロックが20万ほどあり、
分割も検索も遅くて困ってます
該当するブロックは3〜5個程度なので、むしろgrepでマッチする行番号を調べる
→テキストをless等でひらき該当行へジャンプ
→そのブロックをコピペ
の方が早いくらいでして
文字列にマッチするブロックを出力する方法を探してます
たとえば
111
222
222
aaa
222
333
333
333
のようなテキスト中から、aaaを検索した際に、その前後の空白行に囲まれたブロックである
222
222
aaa
222
という結果を得たいです
いまは最初にブロックごとに一時ファイルを作り、それぞれに対してgrepにて検索し
マッチしたファイルを出力、としているのですがブロックが20万ほどあり、
分割も検索も遅くて困ってます
該当するブロックは3〜5個程度なので、むしろgrepでマッチする行番号を調べる
→テキストをless等でひらき該当行へジャンプ
→そのブロックをコピペ
の方が早いくらいでして
2021/11/03(水) 02:48:59.29
Linux板くだ質スレでいい加減嫌われたから流れてきたって感じかな
> ブロックが20万ほどあり
この時点でデータ構造の方を考え直すべき
> ブロックが20万ほどあり
この時点でデータ構造の方を考え直すべき
2021/11/03(水) 06:26:04.06
\n\n(\n...)ではない \nをスペース(やタブなど)に | grep '\<aaa\>' | スペース(やタブなどにしたの)を\nに
2021/11/03(水) 09:59:44.46
テキトーに色々
$ for i in {1..2000000}; do echo aaaa; echo bbbb; echo cccc; echo $i; echo dddd; echo eeee; echo ffff; echo gggg; echo; done > aaa
$ time (awk 'function keepp () { if (matched) { for (i=0 ; i < nkeeps ; i++) print keeps[i]; print } matched=0; nkeeps=0 } NF == 0 { keepp(); next } { keeps[nkeeps++]=$0; if ($1 == "1414213") matched=1 } END{ keepp() }' < aaa )
real 0m10.556s
user 0m10.281s
sys 0m0.271s
$ time (awk 'NF == 0 { print; next } { printf "%s ", $0 }' < aaa | grep '\<1414213\>' | tr ' ' '\n')
real 0m11.101s
user 0m1.177s
sys 0m12.259s
$ time (tr '\n' ' ' < aaa | sed -e 's/ /\
/g' | grep '\<1414213\>' | tr ' ' '\n')
real 0m2.344s
user 0m1.452s
sys 0m0.814s
$ time (tr '\n' ' ' < aaa | sed -e 's/ */\
/g' | grep '\<1414213\>' | tr ' ' '\n')
real 0m3.678s
user 0m1.484s
sys 0m1.078s
$ for i in {1..2000000}; do echo aaaa; echo bbbb; echo cccc; echo $i; echo dddd; echo eeee; echo ffff; echo gggg; echo; done > aaa
$ time (awk 'function keepp () { if (matched) { for (i=0 ; i < nkeeps ; i++) print keeps[i]; print } matched=0; nkeeps=0 } NF == 0 { keepp(); next } { keeps[nkeeps++]=$0; if ($1 == "1414213") matched=1 } END{ keepp() }' < aaa )
real 0m10.556s
user 0m10.281s
sys 0m0.271s
$ time (awk 'NF == 0 { print; next } { printf "%s ", $0 }' < aaa | grep '\<1414213\>' | tr ' ' '\n')
real 0m11.101s
user 0m1.177s
sys 0m12.259s
$ time (tr '\n' ' ' < aaa | sed -e 's/ /\
/g' | grep '\<1414213\>' | tr ' ' '\n')
real 0m2.344s
user 0m1.452s
sys 0m0.814s
$ time (tr '\n' ' ' < aaa | sed -e 's/ */\
/g' | grep '\<1414213\>' | tr ' ' '\n')
real 0m3.678s
user 0m1.484s
sys 0m1.078s
2021/11/03(水) 10:06:32.55
$ time sh smf1.sh
real 0m4.088s
user 0m2.324s
sys 0m3.803s
$ cat smf1.sh
#!/bin/sh
SMF=/tmp/xxx
[ ! -x $SMF ] && { cc -x c - -o $SMF << 'EOS'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
const size_t BUFFER_SIZE = 1024 * 1024 + 1;
char *buffer = (char *)malloc(BUFFER_SIZE);
while (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {
char *ep = buffer + strlen(buffer) - 1;
if (ep >= buffer && *ep == '\n')
*ep = '\0';
if (buffer[0] == '\0')
putc('\n', stdout);
else
printf("%s ", buffer);
}
return 0;
}
EOS
[ $? -ne 0 ] && exit 1; }
$SMF < aaa | grep '\<1414213\>' | tr ' ' '\n'
real 0m4.088s
user 0m2.324s
sys 0m3.803s
$ cat smf1.sh
#!/bin/sh
SMF=/tmp/xxx
[ ! -x $SMF ] && { cc -x c - -o $SMF << 'EOS'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
const size_t BUFFER_SIZE = 1024 * 1024 + 1;
char *buffer = (char *)malloc(BUFFER_SIZE);
while (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {
char *ep = buffer + strlen(buffer) - 1;
if (ep >= buffer && *ep == '\n')
*ep = '\0';
if (buffer[0] == '\0')
putc('\n', stdout);
else
printf("%s ", buffer);
}
return 0;
}
EOS
[ $? -ne 0 ] && exit 1; }
$SMF < aaa | grep '\<1414213\>' | tr ' ' '\n'
2021/11/03(水) 10:07:40.48
$ time sh smf2.sh
real 0m0.717s
user 0m0.381s
sys 0m0.436s
#!/bin/sh
SMF=/tmp/xxx
[ ! -x $SMF ] && { cc -x c - -o $SMF << 'EOS'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
const size_t BUFFER_SIZE = 1024 * 1024;
char *srcbuff = (char *)malloc(BUFFER_SIZE);
char *dstbuff = (char *)malloc(BUFFER_SIZE+1);
char *const de = dstbuff + BUFFER_SIZE - 1;
int numLFs = 0;
size_t len;
while ((len = fread(srcbuff, 1, BUFFER_SIZE, stdin)) > 0) {
char *sp = srcbuff;
char *const sep = sp + len - 1;
char *dp = dstbuff;
char c;
while (sp <= sep) {
if ((c = *(sp++)) == '\n')
numLFs++;
else{
if (numLFs > 1)
*(dp++) = '\n';
else if (numLFs == 1)
real 0m0.717s
user 0m0.381s
sys 0m0.436s
#!/bin/sh
SMF=/tmp/xxx
[ ! -x $SMF ] && { cc -x c - -o $SMF << 'EOS'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
const size_t BUFFER_SIZE = 1024 * 1024;
char *srcbuff = (char *)malloc(BUFFER_SIZE);
char *dstbuff = (char *)malloc(BUFFER_SIZE+1);
char *const de = dstbuff + BUFFER_SIZE - 1;
int numLFs = 0;
size_t len;
while ((len = fread(srcbuff, 1, BUFFER_SIZE, stdin)) > 0) {
char *sp = srcbuff;
char *const sep = sp + len - 1;
char *dp = dstbuff;
char c;
while (sp <= sep) {
if ((c = *(sp++)) == '\n')
numLFs++;
else{
if (numLFs > 1)
*(dp++) = '\n';
else if (numLFs == 1)
2021/11/03(水) 10:07:44.97
*(dp++) = ' ';
numLFs = 0;
*(dp++) = c;
}
}
fwrite(dstbuff, 1, (size_t)(dp - dstbuff), stdout);
}
return 0;
}
EOS
[ $? -ne 0 ] && exit 1; }
$SMF < aaa | grep '\<1414213\>' | tr ' ' '\n'
numLFs = 0;
*(dp++) = c;
}
}
fwrite(dstbuff, 1, (size_t)(dp - dstbuff), stdout);
}
return 0;
}
EOS
[ $? -ne 0 ] && exit 1; }
$SMF < aaa | grep '\<1414213\>' | tr ' ' '\n'
2021/11/04(木) 20:48:41.95
481です
いろいろな方法について情報ありがとうございます
参考にさせていただき、取り入れていこうと思います
いろいろな方法について情報ありがとうございます
参考にさせていただき、取り入れていこうと思います
2021/11/19(金) 02:41:59.96
特定の文字列で始まるファイルが存在するかの判断はどうすればいいでしょうか
ぐぐって見つけた ls を使う方法
if ls $f* > /dev/null 2>&1
then
echo $f で始まるファイルがあります
fi
だと該当ファイルが存在しない場合に
...にアクセスできません: そのようなファイルやディレクトリはありません
というエラーメッセージが表示されます。
また、
for g in $f* ; do
echo $f で始まるファイル $g があります
done
だと該当ファイルがない場合でもループの中に入ってしまいます。
ぐぐって見つけた ls を使う方法
if ls $f* > /dev/null 2>&1
then
echo $f で始まるファイルがあります
fi
だと該当ファイルが存在しない場合に
...にアクセスできません: そのようなファイルやディレクトリはありません
というエラーメッセージが表示されます。
また、
for g in $f* ; do
echo $f で始まるファイル $g があります
done
だと該当ファイルがない場合でもループの中に入ってしまいます。
2021/11/19(金) 03:28:14.33
find使うのはスクリプトじゃないから関係ないか
2021/11/19(金) 10:37:01.91
2021/11/19(金) 10:51:08.20
>>489
あと、forの場合は、シェルが対象がなくてglob展開できない場合はglobそのままの値となる。forの場合に限らずglobはそういうもの
for g in $f*
の場合は、g が $f* になるので、展開されずにそのままなのかチェックするのは必要
for g in $f*; do
[ "$g" = "$f*" ] && { echo 展開できませんでした; break; }
な感じで
あと、forの場合は、シェルが対象がなくてglob展開できない場合はglobそのままの値となる。forの場合に限らずglobはそういうもの
for g in $f*
の場合は、g が $f* になるので、展開されずにそのままなのかチェックするのは必要
for g in $f*; do
[ "$g" = "$f*" ] && { echo 展開できませんでした; break; }
な感じで
2021/11/19(金) 11:01:48.57
>forの場合に限らずglobはそういうもの
なので、
if [ "$(echo $f*)" != "$f*" ]
then
echo $f で始まるファイルがあります
fi
とかとも書ける
zshでnomatchだと余計なメッセージが出るし、>>489のls使ってる方が見た目なにしたいのかわかりやすいと思うけど、いちおう
なので、
if [ "$(echo $f*)" != "$f*" ]
then
echo $f で始まるファイルがあります
fi
とかとも書ける
zshでnomatchだと余計なメッセージが出るし、>>489のls使ってる方が見た目なにしたいのかわかりやすいと思うけど、いちおう
2021/11/19(金) 11:07:42.62
2021/11/19(金) 12:04:30.54
zshネタ、シェルスクリプトではなくて zsh script になってしまうが
null_glob
ってのもあるんだな
setopt null_glob
ってすると、エラーメッセージは出ないわ、globに当てはまらない場合globを入れない/消すわで、>>489のどっちも動くようになるな
そんな応えは求めてないだろうけどw
null_glob
ってのもあるんだな
setopt null_glob
ってすると、エラーメッセージは出ないわ、globに当てはまらない場合globを入れない/消すわで、>>489のどっちも動くようになるな
そんな応えは求めてないだろうけどw
2021/11/19(金) 12:07:54.26
ああ、bashにもnullglobって同じようなのがあるのか
シェルスクリプトという汎用ではなく各シェル固有独特の機能なので使わないだろけど
シェルスクリプトという汎用ではなく各シェル固有独特の機能なので使わないだろけど
2021/11/19(金) 12:11:32.22
2021/11/19(金) 23:23:19.51
489です
ありがとうございます。
とても参考になりました。
ありがとうございます。
とても参考になりました。
2021/11/21(日) 19:09:01.55
コマンドの出力を(だけ)ではなく、シェルそのものの出力(=コマンドの出力もになる)を消すなら
if (exec 1>/dev/null;exec 2>&1;ls $f*); then
echo $f で始まるファイルがあります
fi
て現在のシェル環境を変更(元に戻すのが面倒なのでサブシェルでそこの環境を変更)で消すというのもできたな
if (exec 1>/dev/null;exec 2>&1;ls $f*); then
echo $f で始まるファイルがあります
fi
て現在のシェル環境を変更(元に戻すのが面倒なのでサブシェルでそこの環境を変更)で消すというのもできたな
2021/11/21(日) 19:15:56.45
>if (exec 1>/dev/null;exec 2>&1;ls $f*); then
execのディスクリプタ操作は羅列ができるようなのね
if (exec 1>/dev/null 2>&1;ls $f*); then
の方が良さげか
execのディスクリプタ操作は羅列ができるようなのね
if (exec 1>/dev/null 2>&1;ls $f*); then
の方が良さげか
2021/11/21(日) 22:35:21.95
>>489
check() {
set -- "$1"*
[ -e "$1" ]
}
最短だとこうかな?
set -- "$1"* でシェルのglob展開を用いて位置パラメーターにセットする
ファイルが見つかった場合、そのファイル名が$1に入る
ファイルが見つからなかった場合、"$1"*という文字列が入る
まずありえないとは思うけど"$1*"という名前にアスタリスクが含まれた
ファイルがある可能性を考えると>>492よりも-eでチェックした方が良い
と>>494で書いてあったかw
>>493
> >>489のls使ってる方が見た目なにしたいのかわかりやすいと思うけど
ls $f* は意味がない。シェルのglob展開されてからlsを実行してる。
つまりls file1 file2 file3 のようなものを実行してるだけ。
呼び出す前にすでにファイル一覧を取得してる
単に呼び出しコストが高い[ -e ] になってる
check() {
set -- "$1"*
[ -e "$1" ]
}
最短だとこうかな?
set -- "$1"* でシェルのglob展開を用いて位置パラメーターにセットする
ファイルが見つかった場合、そのファイル名が$1に入る
ファイルが見つからなかった場合、"$1"*という文字列が入る
まずありえないとは思うけど"$1*"という名前にアスタリスクが含まれた
ファイルがある可能性を考えると>>492よりも-eでチェックした方が良い
と>>494で書いてあったかw
>>493
> >>489のls使ってる方が見た目なにしたいのかわかりやすいと思うけど
ls $f* は意味がない。シェルのglob展開されてからlsを実行してる。
つまりls file1 file2 file3 のようなものを実行してるだけ。
呼び出す前にすでにファイル一覧を取得してる
単に呼び出しコストが高い[ -e ] になってる
2021/11/21(日) 23:15:10.23
見た目っ言ってるだろ
そんなコスト気にする必要もないから、見た目とそっちの方を重視してだよ
そんなコスト気にする必要もないから、見た目とそっちの方を重視してだよ
2021/11/21(日) 23:18:58.18
他人の提案を直接ダメ出しして自分の知識自慢をしたがり、
マウント取るのが目的なやつは他のシェルスクリプトスレでも居るけど、
同じやつかな
マウント取るのが目的なやつは他のシェルスクリプトスレでも居るけど、
同じやつかな
2021/11/21(日) 23:19:33.52
lsの見た目の何がいいの?
ファイルリストを取得しても何やってるのか意味わからんでしょ
ファイルリストを取得しても何やってるのか意味わからんでしょ
2021/11/21(日) 23:20:38.15
2021/11/21(日) 23:21:00.73
lsはファイルがあるか確認するのに普通に使ってるだろ、手打ちで
2021/11/21(日) 23:22:25.30
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 事実上の減反政策を法定化へ 農水省方針 「需要に応じた生産」推進 [蚤の市★]
- 【このハゲーっ!】参政党・豊田真由子氏がまたもや“事件”を起こしていた! 「要望が通らないと態度を豹変させ、大声を張り上げて…」 [ぐれ★]
- 【自民党】所得税の増税、27年実施を検討 防衛力強化の財源に [Hitzeschleier★]
- 【北海道】夫の車にひかれ妻が死亡 バックで出庫中後ろにいる妻に気付かず・・ 83歳の夫を逮捕 札幌 [ぐれ★]
- 【鰻】ニホンウナギの規制強化案、ワシントン条約会議で正式に否決 [ぐれ★]
- フジテレビ F1地上波放送11年ぶり復活へ 26年シーズンから最大5戦 [征夷大将軍★]
- 外人「なぜ彼女(高市早苗)は日本で嫌われてるの?」why? [153490809]
- 高市「ひらめいた!東京の税収を地方に配分するわ」 [219241683]
- 日本人「AIで失業?ないない(笑)日本人を舐めるな😡」 AIに対する楽観姿勢、先進国で異例。 [271912485]
- 【美しい国へ】高市「給食費無償化はムリ!」「防衛特別所得税(仮称)を新設」 [219241683]
- 【悲報】所得税増税、2027年1月からWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
- ネトウヨ「今ならまだ中国に勝てる!台湾に積極的に介入し、第三次世界大戦の戦勝国になろう!中国を叩き潰せ!」→5万いいね [314039747]
