シェルスクリプト総合 その30
レス数が1000を超えています。これ以上書き込みはできません。
シェルスクリプトに関する総合スレッドです。
全般
・荒しは無視しましょう。
・丁寧な姿勢を心掛けましょう。
・ネチケット(死語)を意識しましょう。
前スレ:
シェルスクリプト総合 その29
https://mevius.5ch.net/test/read.cgi/tech/1537540487/ お約束
・特記なき場合、Bourne Shell もしくは POSIX 準拠の sh 可換シェルが既定です
つまりシバンは #!/bin/sh です。
特定のシェル(bash, zsh, (m|pd)ksh, (d)ash, yash, posh, fish, (t)csh など)の専用機能に依存する場合は明示しましょう。
macOS (10.14以前), GNU/Linux ユーザー(Debian, Ubuntu 系以外) は /bin/sh の実体が bash なので*特に*注意
自覚なき bashism---シバンが #!/bin/sh なのに bash に依存する構文を使っていませんか?
ただし Debian, Ubuntu などでは /bin/sh の実体は POSIX sh 互換の dash ですのであまり気にしないでも大丈夫です。
FreeBSD ユーザーは /bin/sh の実体が ash なので注意。
Solaris, OpenBSD ユーザーは /bin/sh の実体が ksh なので注意。
macOS 10.15以降のユーザーは/bin/sh の実体が zsh なので注意。
android ユーザーは /bin/sh の実体が mksh なので注意。
csh/tcshでのシェルスクリプトは*まったく推奨しません*。
(参考URL: http://www.speech-lab.org/~hiroki/csh-whynot.euc)
・POSIX に準拠しましょう
有用なリンクは https://en.wikipedia.org/wiki/POSIX にまとめられています。
最新の仕様はこちらへ: http://pubs.opengroup.org/onlinepubs/9699919799/
(左上の「Shell & Utilities」から各コマンドやファイルの仕様を参照することができます)
・Version 7 UNIX の sh(1) に一番近いのは OpenSolaris 由来の Heirloom sh、次点で Debian などに搭載されている Dash shell
Heirloom sh: http://heirloom.sourceforge.net/sh.html
Dash shell: http://gondor.apana.org.au/~herbert/dash/
・UNIX にはシェルスクリプトに便利な小さなコマンドがいろいろあります
Man ページや各種リンク(http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.htmlなど)を見ましょう。
apropos(1) ないしは man(1) の-kオプションでそれらしい単語による簡単な検索もできます。
・ワイルドカードは正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆうな 初心者へのアドバイス
・適した道具を判断するのも頭の重要な使い方。
シェルスクリプトよりも Per lまたは Python の方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたら man(1) を引きましょう。
・思い通りに動かないときは、まずは sh(1) の -x オプションでトレースしましょう。
回答者への注意事項
・相手がシェルスクリプトでの処理方法を質問しているのにもかかわらず、よく知りもせずに「そういうのはPerl, Python使え」と回答するのはやめましょう。
安易に Perl や Python に逃げずに小さなコマンドを組み合わせシェルスクリプトで処理するのが頭のいいやり方。
・質問に対して問題が間違ってるといちゃもんをつけるのも避けましょう。 次スレ立てる時はこのリンクを追加しよう
Bourne shellの種類とか歴史とかシェルの挙動とかいろいろ詳しい
https://www.in-ulm.de/~mascheck/ お約束
・特記なき場合,Bourne ShellもしくはPOSIX準拠のsh互換(というより再現=jシェルが質問・議論の前提です。
つまりシェルスクリプトのシバンは#!/bin/shです。
他のシェル(Bash, Zsh, Ksh, BusyBox sh, DASH, Yash, posh, fish, (t)csh)などの専用機能に依存する場合は,その旨を明示しましょう。
macOS及びGNU/Linuxの利用者は/bin/shの実体がbashなので*特に*注意; 自覚なきbashism――シバンが#!/bin/shなのにBashに依存する構文を使っていませんか?
※ただしDebian, Ubuntuなどでは/bin/shの実体はPOSIX shにかなり近い(つまり独自の拡張がほとんどない)DASHですのであまり気にしないでも大丈夫です。
FreeBSDの利用者は/bin/shの実体がashなので注意。
Solaris及びOpenBSDの利用者は/bin/shの実体がKshなので注意。
(t)cshでのシェルスクリプトは*まったく推奨しません*(参考: http://www.speech-lab.org/~hiroki/csh-whynot.euc)。
・POSIX (Portable Operating System Interface) に準拠しましょう。
有用なリンクはhttps://en.wikipedia.org/wiki/POSIX末節などを参照。
最新の仕様はこちらへ: http://pubs.opengroup.org/onlinepubs/9699919799/
(左上の「Shell & Utilities」から各コマンドの仕様を閲覧できます。また,コマンドだけでなく,ファイルその他の仕様も閲覧できます)
・Version 7 UNIXのsh(1)に一番近いのはOpenSolaris由来のHeirloom sh,次点でDebianなどに搭載されているDASH。
Heirloom sh: http://heirloom.sourceforge.net/sh.html
Dash shell: http://gondor.apana.org.au/~herbert/dash/
・Bourne shellの種類・歴史やシェルの挙動とかいろいろ詳しいサイト: https://www.in-ulm.de/~mascheck/
・Unixにはシェルスクリプトに便利な小さなコマンド類がいろいろあります。
「並び換え (sort(1))」「検索 (grep(1))」等々。
Manページや各種リンク(http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.htmlなど)を見ましょう。
apropos(1)ないしはman(1)の-kオプションでそれらしい単語による簡単な検索もできます。
・ワイルドカードは正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆうな なんかどうも理解してないようだから、続きのひとレス
動くかどうかの問題無いじゃないんだよ。cat 以後の cat の出力に対してのという表記に見えるのが好みじゃないってとこなんだよ。わかるかなあ?
例で cat | while でやることと、前処理と前処理の調整は別のもん。なのにってとこだよ。そこが無理してんなということだよ。わかるかなあ?まあ、わからんだろうけど
そういう「俺の好み」からはナイなということだよ。言ってもわからんだろうけど、いちおう最後にということで 明確な理由がなくて、単に好みとだけ言ってたら
賛同を得られないのは当たり前。
bashはだめだよ。好みじゃないもの(笑) 変数のスコープを考えろって話だ。
前処理だろうが、後処理だろうが、
変数を参照するならば、同じ階層(かそれ以下)でなければならない。
関数の外で、関数内の変数を参照しようっていうのがそもそも間違い。 例えば、
hoge=0 # ← ==== ここで変数定義 ==== ・・・ (A)
while IFS= read -r line; do
[ なにか ] && hoge=1
ほかにいろいろ
done < <(cat)
if [ hoge = 0 ]; then # ← ==== ここで使用してる ====・・・ (B)
前処理の調整
else
前処理の調整
fi
というコードの場合、少なくともAからBの間は
同一スコープ(=サブシェル ≒ 関数)内になければいけない
関数内で定義したローカル変数は、関数内でしか参照できないのと一緒。
これぐらいはすぐに理解しよう。 関数の中で、前処理、後処理(前処理の調整)を
したくないっていうのなら、こうなる。
foo() {
hoge=0
while IFS= read -r line; do
[ なにか ] && hoge=1
ほかにいろいろ
done
[ hoge = 0 ]
}
前処理
if cat | foo; then
前処理の調整
else
前処理の調整
fi
これはもうシェルスクリプトがどうとかいうんじゃなくて、
個人のプログラミング技術レベルの問題
まともな設計能力があればできること
ワンライナーとかシェル芸とかばっかりやってると
こういうプログラミング能力が身につかないのかもなw 別にそれでいいよ。別に俺はあなたにそう使うなとは言ってないし、bashのを使えとも言ってないけど?どう書くのかなあと聞いただけだよ、理解してお礼も言っているのにw
あなたが根本的に勘違いしているのは自分は正しい他は間違いってとこだね。賛同とかw別にあなたに賛同を求めてはいないよ?はなから。
>>9は無茶苦茶。なにかひどく後で出た巻数にすればいいに自信を持っているように見えるんだが、勝手にいろいろ妄想しすぎです
なんか異常に自分は正しいに拘るのね。わからん >>7
正直,お前の好みと可搬性だったら可搬性を優先するわ。 >>12
お前なんの話してるの?
POSIX準拠だとサブシェルの中で変数を書き換えられないって
言ってたから、正しいプログラミングをすれば、それは問題にならないって
実例を上げて説明したんだが?
で、お礼も言わずに「俺の好みじゃない」と言ってるだけじゃん うわっ。なんか他の言語で当たり前の事をながーく書いてるねえ
他の言語と同じように書けるっぽいのがbashの方だと思うんだけどねえ
>>7で書いた通りのままだな。やっぱりわかってないようだし、コロコロ表記変わるよりは、bashのでのほうが変わらない普遍的だなというw結論で、俺は納得しておしまい [[ "$VAR" =~ '<regexp>' ]]
↓
expr "$VAR" : '<regexp>'
for ((i=0;16>i;i++)) ; do
echo $i
done
↓
i=0; while [ $i -lt 16 ]; do
echo $i
i=$((i+1)); done
ていうか >>11 あたりの「自分の好み」じゃなくて「POSIX規格」に基づいて考えを述べてくれる人に聞きたいんだけど
俺の↑この下段のシェルスクリプトって上段のシェルスクリプトと同じ動きをして,かつPOSIXに準拠してるよね。
何か問題があればツッコんで欲しい(自分では上手くいくと思っているので)。 >>14
俺の最初のレスをよく読もうな。そしてお礼を言ったレスもよく読もうな やっぱりわかってない → 何がわかってないのか? → 何も言わずにまた逃げる
このパターンなんだよなw >>17
サブシェルになると、変数が書き換えられなくて困る(?)とかいう話らしい
困らんのだがねw まあ...なんだな自分の世界で生きている人だな。そんなにレス書けているんだから読むくらいできるでしょwすげえな >>13
ちょっとショックと思ったら>>17で納得したwなんだかな あたりまえの事言われてるのにショック受けててかわいい ちょっとキモいっす。あなたにとってあたりまえでしょ>>17と勧めた人だもの >>21
なるほど……。
あんたもレスしてたけど
シェルスクリプトにおける変数のスコープってC言語やJavaScriptなんかとほぼ変わらない規則だよね。
「POSIXに準拠したシェルスクリプトは『普遍的』じゃない」っていう主張と矛盾してるよなw シェルスクリプトにはPOSIXの範囲ではグローバル変数しか無いけれど
(localやtypesetはPOSIXではない)
サブシェルまで考えると、ローカル変数として使えるんだよな。
よく考えられた言語だと思うよ。 プロセスが別だからというだけだけどね。よくは考えてないだろう ID: uO4UDEG+の主張をなるべく中立的に列挙してみる。
・「自分が好きな書き方」のシェルスクリプトがある。
・それを人に強制する気はない。
↑これで合ってるよね。
ただ自分がこの人に賛同できない点は二つあって
1. 肝心の「自分が好きな書き方」の規則や具体例をほとんど挙げていない。
例えば「サブシェルをできれば使いたくない」とかそういう好みを言わずに,
人が書いたシェルスクリプトを「これは自分の好みに合わない」って言ってる。
2. 規格に準拠した書き方と「自分が好きな書き方」が同等の立場にあると思っている。
これは賛否あるかも知れないけど,好みの書き方が規格に準じてなかった場合,
大抵の人はそのプログラムを規格に準じた書き方に直すと思う。
たとえその書き方が嫌いだったとしても。 >>28
Bashとかだとわざわざlocalっていう新しい予約語を用意してるけど
正直無駄っちゃ無駄よね。
POSIX準拠のシェルスクリプトでもほぼ可読性を損なわずに局所変数が定義できるから。
ところでBashの拡張機能で素晴しいと思うのは配列だね。
これはPOSIXに準じたシェルスクリプトではなかなか実現できない。
実現できたとしても大抵は複雑奇怪でデバックも地獄。 forkはプロセスのコピーなので、親プロセスの変数なんぞはそのまま使える。だがしかし返すことや親プロセスの変数を変えることはできません
ってだけだね、確か
>>30
1.すでに言ってるけどなあ。最初から言えっていう?bashでのスッキリした書き方がわかっているもんだと思ったから
2.「同等の立場」とか何言っているのかわからん。どこでも誰でもPOSIXでなければならないとか言ってないでしょ?何を言っているのかわからん。bashでいいならbashを使ったそれに準じたでいいでしょね >>31
おいおいおいおい。>>27と言っておいて、それも人をそれをネタに揶揄しといて、それないないw >>33
「矛盾している」という指摘を「揶揄」と捉えてしまうような人とはお話できませんね……。 >>34
その「矛盾している」という元はなんだったのか自分の書いたレスをよく読んできてね(そもそも普遍的でないは別にスコープとは無関係なことでなのに急にという)
スコープがPOSIXでは無かったら、bashでできるようなのは無駄とか言っちゃってるんですけど?ちょっと酷すぎね?w >>32
> どこでも誰でもPOSIXでなければならないとか言ってないでしょ
いや,今回に限ればそれは違う。
https://mevius.5ch.net/test/read.cgi/tech/1537540487/962
でPOSIXでの書き方を訊いた人がいて,それに関して
https://mevius.5ch.net/test/read.cgi/tech/1537540487/971
を提示すると
https://mevius.5ch.net/test/read.cgi/tech/1537540487/972
でID:uO4UDEG+が「その書き方は嫌いだ」という主張をしている。
つまりID:uO4UDEG+は少なくとも前スレ972においては
「POSIXに準じた書き方」と「自分が好きな書き方」を比較している。
たとえ無意識的だったとしても,たった2つ前のスレを読んでさえいれば
前スレ971で(俺が)提示したシェルスクリプトがPOSIX準拠を念頭に置いて書いたものだと分かる筈。 >>36
いやいや。POSIXでも「同等」に書ける?と聞いているし、whileを使ったのもそれは嫌と言っているでしょ
根本的にPOSIX第一主義にあなたの思いが強すぎて読めてないよ、たぶん >>29
サブシェルはプロセスを別にする必要はないよ。
実際にkshはサブシェルだけど別プロセスにならない場合がある >>38
そういう場合は変えられるんじゃないの?でないと、わざわざメモリガードというか別メモリを用意してとかめんど臭いことしなきゃならないだろうね >>31
配列が出てくるのはシェルスクリプトのプログラミングスタイルがわかってないんだと思う。
一行一データで行指向で処理するのがシェルスクリプトだから
ツリー構造のデータにRDBMSを使うようなもん >>39
> そういう場合は変えられるんじゃないの?
主語をはっきりさせろ。誰にも伝わらん。
> わざわざメモリガードというか別メモリを用意してとかめんど臭いことしなきゃならないだろうね
だからkshは面倒くさいことをして
(特定の条件を満たす限り)サブシェルを別プロセスにしてない。
そういうことをしてOKだし、そういうことを想定してるから、
サブプロセスではなくサブシェルという別の言葉を作ってる >>40
まあ,そう言われればそうだな。
俺も,シェルスクリプト大好きですみたいな雰囲気のくせして,
シェルスクリプトで面倒な操作が要求されるような場合は
すぐにC#やPython3に浮気するからなw >>41
サブシェルが別プロセスでない場合だよ。プロセスが別かどうかの話なんだからわかるかと思ったけどなあ
ということは、同一プロセスでも変えられないのね。「ksh」はそこは「よく考えるんだな」と言えるでしょうね。なんでまたとも思うけど。古のshは別プロセスの方だろうと思うけどどうだろう >>43
だから、何を何に「変えられる」のか言えって >>37
別に俺はPOSIX第一主義でもなんでもない。
というかPOSIXに従わないという明確な方針があるならそれはそれでいいとさえ思ってる
(あまり賛同しずらいけど)。
ただし今回はPOSIXに準拠したものと「同等の」シェルスクリプトを書く話だから
俺はPOSIX規格を持ち出してきてる訳。 >>44
ああ、「変数を」の方か?それも以後の文でわかってるでしょうに。まあ、いちおうすまん。なんか納得いかんから「いちおう」。だか「すまん」もあるよ
なんかめんどくさいやつだと思ってしまうぞw しっかし……なんでそう極端にしかモノを考えられないのかね。
たぶん,彼が想像する世界には「POSIX絶対!」っていう人と「Bashizm最高!」っていう人の二種類しか存在しないのかもw
だってそうじゃなきゃ(限定的に)POSIXの話をしている中に割って入って「POSIX第一主義だ」なんて言えないもん。
(というかそういう発想がまず出てこないw) >>45
そうなの?だったら単に読んでなかっただけか??
「同等」がそういう「同等」ではないと、元の人がすでに言っていたわけだったのよ POSIXシェルの範囲でできることなんだから、POSIX準拠でいいやん
これだけだろ。
POSIX準拠じゃできないことならまだしも、
POSIX準拠でできるならPOSIX準拠で作ってりゃ可搬性も有るし。
必要もないのに [[ ]] を使うやつ多すぎ >>47
「読んでなかった」とは思えんし、スコープでの豹変からそう判断せざるを得なかったなあw 他にもね
こちらからもあなたが極端と見えるんだけどねえw >>49
そゆとこだよ、あなたの悪いwとこは。やっぱり自分が正しく他の人の好みは認めんってだけやん >>48
元の人というのはID:Tm8GOmHyだよな。
この人物のその後の発言は
https://mevius.5ch.net/test/read.cgi/tech/1537540487/967
しかないのだが,ここから
「POSIXと『同等』のシェルスクリプトというのは
POSIX規格に準拠したシェルスクリプトのことではない」
という主張は俺にはどうしても読み取れんな……。 >>51
「POSIX準拠でいいやん」
これを
「POSIX準拠以外は認めない」
って読み替えてしまうのヤバくない? >>52
なにを言っているのだかだよ
>while は見た目簡潔じゃないし、インクリメント忘れる可能性もある
という拒否だよ、彼の好みからの。「同等」の意味をまだわかってないねえ 「POSIX準拠でいいやん」という意見を認めたくないんだろうね(笑) >>57
すいません,ここでの「『同等』の意味」を教えていただけますか。 >>57
そういうとこやで、
わかってないねぇ → 何が? → 何も言わずにまた逃走
お前、自分の意見を何も言ってない。
そういうとこやで >>53-55
あなたたちとの違いは、
>必要もないのに [[ ]] を使うやつ多すぎ
とかいうのと同じようなこと言ってないよ。俺は別にあなたにPOSIXにこだわって書くなとは言ってないよ?好きにすればだよ
あなたのこの言葉はそれと同じとでも言うの?
なんであなたの好みを他人に押し付けるの?なにか意味あんのそれ? >>59
全く同じに近い同等だろう、whileでさえ拒否するあたりは
>>58,60
何を言っているのだが、一人で悦に入るねえ、たびたび
俺はあんたらにああしろとは言わない。それが意見を言ってないというならそうだろうが、まさかそう言っているわけ? >>62
あーなるほど。
Bashの独自文法で書いたシェルスクリプトと限りなく同じ見た目のものを要求してた訳か……。
うーん。これには助けにならないな。
少なくとも俺はPOSIXに準じつつかつfor (())文みたいな「見た目」のシェルスクリプトを書けない。 ああ、ああしろとは言ってるな「好みを押し付けるんじゃねえ」とw >>63
sed -e 's/助けにならない/助けになれない/' >>63
ご理解いただけて嬉しい限りでございます。彼の本音とかわからんけどねw 全く同じじゃないとだめとかアホだろw
同等のコードがかければ問題ない。 好みを押し付けるんじゃねえ
って繰り返すだけだな、もうwアホとか馬鹿にしなきゃならないほどのあんたの心理がわからん >>63
> 少なくとも俺はPOSIXに準じつつかつfor (())文みたいな「見た目」のシェルスクリプトを書けない。
ほらよ。関数を作ってPOSIX準拠でコレが動くようにしたで。これなら満足やろ?
forloop i=0 'i < 2' i+=1; do
forloop j=0 'j < 10' j+=2; do
echo "$i $j"
done
done
出力結果
0 0
0 2
0 4
0 6
0 8
1 0
1 2
1 4
1 6
1 8
forloop の実装はお昼ごろ公開(笑) >>69
おーすごい。
単に三つの引数を取って処理するだけじゃ
doやdoneキーワードをシェルが認識できないから,
そこをやりくりする必要があるな。
俺には思い付かんわw まとめるとどこでも動くシェルスクリプトなんて都市伝説ってことだね。
だってめんどくさすぎるもん。
普通に書いたらその実質環境専用。 POSIX原理主義的にはアウトなんだろうけど
俺なら素直にseq使うな
for i in `seq 0 1`; do
for j in `seq 0 2 9`; do
echo "$i $j"
done
done 仮定の話として、
bashのがPOSIX規格に入ったとして、方々の環境で使えるようになったとしても、
それを使わずに独特なあんなのを書くのだろうか? 慣れの問題じゃないかな
人間は最初に覚えたものを正しいとする傾向があるからね >>73
seqをシェルスクリプトで実装すればOK。簡単でしょ?
でもそれだとiをループ内で更新できないからだめなんだと
そんなことしねーだろうに、条件がよくわからんわw >>78
例のawkプログラマのコードか
そんな無駄に実装しないでいいやん
単に数列を返す関数を作ればいいだけ bash のfor ループで、5分ぐらい掛かるものが、
awk, Perl, Ruby などでは数秒以内
dash なら、まだマシ × bash のfor ループで、5分ぐらい掛かるものが、
○ bash のfor ループで大量に外部プロセス呼び出ししたから5分ぐらい掛かる。俺ってなんて馬鹿だろう では>>69の解答(こんなコード書かないで普通にwhile使うわw)
iterator() {
case $iterator in
?) eval ": \$(($3)); [ \$(($2)) = 1 ]" ;;
*) eval ": \$(($1)); iterator=1" ;;
esac
}
alias forloop="iterator=; while iterator"
forloop i=0 'i < 2' i+=1; do
forloop j=0 'j < 10' j+=2; do
echo "$i $j"
done
done あ、bashの場合のコード忘れてたw
[ "${BASH_VERSION:-}" ] && shopt -s expand_aliases やっぱりどこでも動くシェルスクリプトなんて現実的じゃないね。 >>74
そんな訳なくね?
だってBashの構文がPOSIX規格に採用されたということは
「好みの」問題でBashの構文を書いたとしてもどこでも動くシェルスクリプトが書ける訳でしょ。
俺はどーでもいいけどBashの構文を書きたい&&POSIXに準拠したい人は,
当然Bashの構文で書くようになるだろうね。 POSIX準拠コマンドの選定基準ってあるのかね
seqのないシステムなんて見たことないんだけどな BSD, GNU系だからってことか
でも Solaris(SYSV系)にも入ってたはずだけどな
選定基準はBSDとSYSVの共通項とる感じなのかね seqは初期のUnixの頃にはいらない子だったんだなと
https://en.wikipedia.org/wiki/List_of_Unix_commands
コマンド初出元は方々だね、基準がわからない。お話し合いでじゃないのかな
trは不人気もありお話し合いで上がらないか却下とか なるほどね
そろそろ改定してもいいんじゃないって思うな
今どき SCCSなんて使ってないでしょw >trは不人気もあり
seqは不人気もありの間違い
なんか今でもコマンドの内容については議論しているようだけどね。コマンドの選定とかもあるかな。議論を見ると時間がかかるのが明らかだけど >>93
それな。
ていうかまず書庫作成コマンドにおけるpaxみたいに,
ネットワークを扱う中立的なコマンドを作って >>83
それってどうしても
alias使わないと無理? >>96
whileループが1回目の場合にループ変数に初期値の設定、それ以外は加算する必要がある。
だからループの1回目かそれ以外の区別する必要があるんだけど、他にいい方法が思いつかなかった。
見た目まで合わせようとするとこうなるかなと
ま、普通にwhile使えばいいんで、こんな事しないけどねw あとaliasを使えば、簡単な文法の変換を行えるわけだけど、
aliasを使わないならば、forloop i=0 'i < 2' i+=1; do とは書けずに、
while iterator i=0 'i < 2' i+=1; do のようにwhile と iterator の最低二つの単語が必要だろうね。 hoge.sh の中で bash hage.sh と実行した時に、なんでなにもしてないのに
hage.shの中ですでに環境変数などが設定されてるんだ?誰が設定してるんだ?って思ったら
BASH_ENVにファイル名を入れておくと、bash hage.sh実行時に
指定されたファイルを読み込むのか・・・ > hoge.sh の中で bash hage.sh と実行
素人質問で済みません、これは無限ループにならないのでしょうか?
ならないなら、どういう仕組みで阻止されてるのでしょうか 無限ループに条件つけて終了させればいい
どの言語でも一緒 あー、シェルが勝手に阻止してくれるワケではないのですね...
#! /bin/sh
echo "foo!"
bash hoge.sh
これ無限ループになりました。 hoge、fuga、piyoは認めるがhageは認めんぞ
俺が禿げているって訳じゃないぞ本当だからな )ソ)
ッλ ノ(.,ノ)
(゙- ..::.::. . (
(ソ. .彡⌒ミ. )ソ)
).::'; (´・ω・`) ス (
ソ .::;';'(つ ⊂)::;';'`〜、.
( :;';' |__∧_| ::;';' ヽ)
`'~`'''`'`'`~'~~`~~'`'`''''"`'`'`''`''''"`'``'~`''`'~`'''`'`'`~
さ あ 禿 げ 上 が っ て ま い り ま し た >>101
$SHLVL変数で判定するんじゃないの? ……と思ったらhogeとhageかよw
クッソwww紛らわしいメタ変数使うなw
普通hogeの次はfugaだろーがよ commandって便利やな。
シェルスクリプトでオーバーライドができちゃうよ >>112
ls () {
command -p ls
}
↑こういうやつなw command て.... ググラビリティ低すぎでしょ >>114
いやもっとググビティ低いのでmanとかありますし……。
あとcatもかな?make・niceあたりも引っ掛かりにくい。
でもまあ関連語句と一緒に検索すればノイズはほぼ無くなるけどね。 less より vi(/= vim) が軽いので
ページャーとしてパイプの最後に less するのとりかえる シェルスクリプトで、実行結果にかかわらず終了コード0を先出しする書き方ってないでしょうか。
背景としては…
openvpnのServer側で、「clientが接続してきたらコマンドを実行」できるんですが、
そのコマンドの終了コードが0でないと以降の処理が進まず、接続が確立されないようなんです。
今回コマンドの目的は「SSHでclientにコマンドを送り込むスクリプト」なので、
コマンドの実行結果なんか見ないで先に接続を確立してくれないと、送り込みようがないです。
なのでopenvpn側には、スクリプトの結果にかかわらず終了コード0を先に返しておいて、
sleepを入れるなり何なりして後からSSHでコマンドを送り込みたいんですが、
/path/to/script.sh && true とか色々試してみるも、一向にスクリプト終了と見なしてもらえません。
何か方法はないでしょうか。 /path/to/script.sh; true
これじゃあかんの? catとtac
lsとsl
moreとless
nanoとmicro
headとtail
こいつらみたいな言葉遊びって他にもある?
大抵は既存コマンドの改良版が対にされやすいよな >>117
/path/to/script.sh & true
script.shをバックグラウンドで実行でいいんじゃないの >>117
終了コードを先出しするの意味がわからんが、
まあ中断しないようにしたいということだとして。
まず途中で中断するのは set -e されてるから
set -e されてる状態だとコマンドの終了コードが0以外だとそこで中断されてしまう。
中断されなくする一番簡単な方法は
hige ||: ・・・終了コードが0以外でも中断せず、かつ終了コードを0にする
hige &&: ・・・終了コードが0以外でも中断せず、かつ終了コードはそのまま保持する
あと、if hige; then 〜 みたいに if や while の中に入れてもOK
if や while は、コマンドの終了コードを条件に処理を分岐するので
これらの中に入れても中断しなくなる。 >>117
どうでもいいけどさ、openvpnの機能で
たしか接続時にスクリプト実行する機能がなかったか? >>119
yacc→bison
cat→dog
make→kati (https://git.io/fj6cL) >>118,120
;も&もダメでした。
>>121
ちょっと理解し切れてるかわかりませんが、
;や&の代わりに||を試しても、同じ結果でした。
>>122
その接続時スクリプト実行機能で、自作スクリプトを実行しようとしているが、
自作スクリプトのexitcode 0を確認しない限り接続が確立されないので、
接続できている前提の自作スクリプトがうまく動かない、という話です。
その後、試行錯誤してうまくいったんですが、
・openvpnの接続時スクリプト1は、別のスクリプト2を&付きで実行してすぐexit 0で終了
・別のスクリプトにやりたい処理を記述、終わったらexit 0
こういう方法でした。 今さらだけどPOSIXでpushdとかって「未定義」なんだな。
つまりこれらの字句が来たとき、pushdコマンドが実行されるかもしれないと想定しなきゃいけない。 >>124
これは?
/path/to/script.sh ; exit 0 俺には >>120 と >>124 でうまくいった方法が同じに思えるのだが何が違ったのだろう... >>119
more most
nano pico
perl ruby >>126
明日試してみます
>>127
そもそもopenvpn側の判定条件がはっきりしてないので、
シェルスクリプト的には皆さんに教えてもらったのが正解でも
openvpn的にダメってだけかもしれません。
シェルスクリプト的にokならそれでokじゃないはずがない、とは思うんですが。 >>129
openvpnの
--client-connect
か
--route-up
を使えばいい気がする >>125
もとはcshの機能だからPOSIX策定時は独自拡張だったんだろうな
POSIX準拠のシェルスクリプトではpushd,popd,dirsは使わない >>129
スクリプトではなく純粋にコマンドの実行=単に実行ファイルの実行とか
引数の解釈分解もopenvpnでやってるとかかな?であれば、
/bin/sh -c '/path/to/script.sh & true'
とかなんとか。書き方も違うかもしれない(' が必要なのか可能なのか、もしかしたらできないとか) POSIXユーティリティにネットワーク関連のコマンドが追加される予定ってあるの? >>128
perlはもともとどういう意味だったんだろうな。 >>134
確か pearl って言語が既にあったので perl にしたんだったと思った。 >>135
そういういえばteeのパイプ版のpeeというのもあった。 >>139
それは「pooコマンド」があるってこと?
検索してもネットミームしか引っ掛からんw sexという天文学用のコマンドがある事実
下ネタ満載のmanもあるらしいが s式の expression という意味で lisp では
sexp というワードが使われる時が sex ちらつく
シェルスクリプトじゃなくてごめん セマンティックバージョニングの並びで最新のタグを取得するにはどうすればいいの?
sort -Vはposixにはないようなんでなしで。
gitコマンドで(最後に付けたタグではなく)最新のタグが取得できればそれでも良いんだけど >>153
試してないけどsortの区切りオプションを“.”にして
各桁を数字順に並び換えたら上手いこといきそう。 1桁目を並び替えて、それから2桁を並び替えて、それから3桁目を並び替えるってできるんかいな?
できたとしても、1.0.0 よりも 1.0.0-alpha は小さくなって、
1.0.0-alpha と 1.0.0-beta はASCII順で後者のほうが後で、
1.0.0-alpha と 1.0.0-alpha+20190710 は順番が同じなんていうルールが有るわけだけど 素直にsort -V使うのが一番。
POSIXに準拠したければそれなりの実力がないとね。
少なくとも俺には無理w ていうかわざわざ既にある機能を苦労して再発明したくねーw つまりどこでも動くシェルスクリプトなんて都市伝説だよね。 世界征服して一つのシェルしか使わないように全世界の人間に強制すれば可能 シェルスクリプトは「完全に」どこでも動くとは限らないけど
他の言語と比べて「ある程度」どこでも動く確率が高い。 確率を言うならデータもってこいよ
どこにあるんだよその統計はw それいわれたのC があって perl ができる前の常識でしょ
C よりは確かに移植性ある Windowsには最初からは入ってないよね?今のは入ってる?
まあ WSL 動かしちゃえば何でもありにはなるが。 そんなに難しい話じゃなくてshは多くの環境にインストールされてるってだけのことでしょ?
例えばPerlが初期インストールされてるような環境なら
必ずshもインストールされてる。
Perlが入って無くても、shはインストールされてる。 >>165
Windowsにはshが入ってないけど、
PerlやRubyも入ってない。
shが入ってないならば、○○も入ってないが成り立つ。 結局の所Windowsとそれ以外のOSに分かれるわけで、
Windowsとそれ以外のOSの両方に入ってる言語はなくて、
Windows以外のOSに入ってる言語で一番多いのはshなんだよね。 dockerとか使うとわかるけど、最小イメージのalpineには
perもrubyもpythonも入ってないからな そういやalpineにはbashですら入ってないのな /\___/\
/ / ヽ ::: \
| (●), 、(●)、 | / ̄ ̄ ̄ ̄ ̄ ̄ ̄
| ,,ノ(、_, )ヽ、,, | < まーたはじまった
| ,;‐=‐ヽ .:::::| \_______
\ `ニニ´ .:::/
/`ー‐--‐‐―´´\ 要はPOSIXは必要最低限の機能しか規格化していないから出来ることには限界があるってことだ Windowsにはshが入ってない!
→ かといってじゃあ他の言語が入っているかというと入ってない
Windowsは諦めた。それ以外で最初からOSに入っていてどこでも使える言語はなんだ?
→ sh /\___/\
/ / ヽ ::: \
| (●), 、(●)、 | / ̄ ̄ ̄ ̄ ̄ ̄ ̄
| ,,ノ(、_, )ヽ、,, | < まーたはじまった
| ,;‐=‐ヽ .:::::| \_______
\ `ニニ´ .:::/
/`ー‐--‐‐―´´\ まじで?
買ってきたばかりの ノートブック windows でも? 買ってきたばかりの ノートブック windows でも
Perlなら動く!→動きません(笑)
Rubyなら? Pythonなら? C言語なら? NO!!!! Windowsに最初から入ってるのは vbs とか js とか、あとバッチファイルとかパワーシェルかな。よく知らんけど。
HTAってのもあったっけ。 powershell考えた奴は頭おかしいんじゃね
なんでいちいちコマンドとかあんな長いんだよ
無能にもほどがある adduserとuseraddどっちがどっちかたまに使うとき毎回調べるみたいなクソ下らないことしたくないからじゃない? それをいうなら、Windows、Macで、どの言語でも構わないが
ユーザーを追加する方法を調べないでわかるっていうの? POSIXってUNIX系OSの規格なのに
なんでWindowsの話になってんだよw >>188
>Javaなら一度書けばどこでも動くのに
とあったから
Windows は標準でいれてるのかなと javaのコンセプト
write ones, test everywhere Windows, WSL, Ubuntu16.04 では、Python, Perl は最初から入っている。
Ruby は、apt でインストールした
ls −l /usr/bin/python
/usr/bin/python −> python2.7
ls −l /usr/bin/python3
/usr/bin/python3 −> python3.5
ls −l /usr/bin/perl
/usr/bin/perl
ls −l /usr/bin/ruby
/usr/bin/ruby −> ruby2.3
注意。サーバーエラーになるので、全角に変換した そういえば IBM の z/OS ではどうなっているんだろうと
思ったら z/OS シェルってのがデフォルトでインストール
されてて、こいつは POSIX compliant らしい それだ WSL が標準で最初から入っているようになると
昔のニュースで見たが、どうなっているの?
標準は取りやめ? Windows の最新情報追ってないからわからない Windows10 を普通にアップデートしていれば、WSL は、最初から入っている。
ストアから、Ubuntu18.04 (長期サポート版)などをインストールして、日本語化すればよい
漏れはまだ、古いUbuntu16.04 の方を使っているけど >>184
あれは、普段使いのCUIではないからな
単なる開発用 個人的には、*nixとWindowsの違いは、
シェルと馴染んだコマンド群の有無、シェルスクリプトの実行可否だけなので、
それさえできれば、どちらでもいいや。
Cygwinはややストレス溜まったけど、WSLはだいぶ快適になった。 cmdのオプションが/なのは当て付けなんだろうか
XENIXを売ってた頃のMS知らんけど 階層がないファイルシステムだと - でも / でもどっちでも違和感が無いのだろう
単に好みでそれにしたってだけじゃないかな
階層があるようになって / を好みで選んで失敗したと思ったけどどうにもならななかったよう
手立ては用意したがサードパーティがそれを使わないとか ああ、どうにもならなかったのは、
オプションを/にしてしまったからとりあえずパス区切りはバックスラッシュにしたよ、でも、/ にもできるよ
だった。オプションを - に変えるのは今でも前のいつでもできるだろうな
コマンドによっては別の意味を持たせてとかありそうだが、なんの拘りなんだかよくわからんな 同じPCで一つがWSL1上のUbuntu、もう一つがDocker上のUbuntuで
lsb_release -aしてどちらも同じUbuntu 18.04.2 LTSなのに
kshのシェルに入ってから以下のコマンドを実行すると違いがある
echo $((99999999999999999))
=> 100000000000000000 # WSL
=> 99999999999999999 # Docker
KSV_VERSIONは両方とも同じ Version AJM 93u+ 2012-08-01
カーネル関係なさそうなのに、なんでだろう? ディレクトリごとの正確なファイル数が高速に知りたいです。 ls より find が早い
再帰ディレクトリ探索とファイル名出力はそれに任せて
その出力をパイプで変換していったらいいんじゃないか? なぜduでファイル数も調べられるようにしなかったのか? やるべきことは最小限の1つ
UNIXの哲学でしょ
小さいから早い
小さいからパイプでつなげていろいろ実現できる
小さいから保守できる その理屈だと、lsコマンドはファイルの名前だけじゃなくて
ファイルサイズまで表示している。
最小限になってない。findコマンドを見習え
って話になるんだがw >>209
ファイルを数えるのはduの仕事じゃないから ファイルを数えるのは誰の仕事?
仕事は一番うまくできる人がするべきですよ そういやファイル名に改行が含まれる場合、
POSIX準拠コマンド&オプションだけで数えられるの? やるべきことは最小限っていったら
duコマンドなんていらんよな
findでファイル検索して、lsでファイルの情報出して
awkで加算すれば良い
パイプでつなげていろいろ実現できる >>205
>>206
long doubleを使っているんだと思う。long doubleは昔のx87 fpuで計算されることになるが、これは精度を設定できて、確かデフォルトがlinuxでは80bit、windowsでは64bitになっていたと思う。 >>217
でもWSL版Ubuntuと通常のUbuntuでバイナリは同じはずでしょ?
FPUモードの設定とかあるってこと?
同じ命令でもモードによって精度が違うとか 元々、浮動小数点は誤差があるから、どっちでも良い
誤差無しなら、プログラミング言語で、Decimal などのライブラリを使わないといけない >>212
ls 凄いよね
呼びだした端末の表示限界まで調査して
整列してくれる
最小限だけではものたりないから Emacs とかできたんじゃない? >>207
$ find 〈対象ディレクトリ〉 -type f | wc -l bcコマンド使いなよ。POSIXで定められたほとんど唯一といっていい任意精度演算ができるコマンドだぜ。
残念ながらなぜかUbuntuには初期状態で入っていない……。 >>207
find ~/web -type f | perl -pe 's{[^/]+$}{\n}m'|uniq -c
27 /home/web/
11 /home/web/elona/
5 /home/web/elona/.git/
9 /home/web/elona/.git/hooks/
1 /home/web/elona/.git/info/
... やっぱりシェルスクリプトのパイプやばい
たった1行の短いのでそこそこ早いのが書きあがっちゃう >>220
emacsは出自がUnixじゃないから ちなみにPlan 9(Unixの後釜)のlsはもっと洗練された体系になってる。
あとPlan 9のEmacsの手引書がおもしろい Plan 9も最初からGPLで公開していればLinuxと肩を並べてたかもね >>218
FPU制御レジスタをFLDCW命令で変更すると計算精度や丸め方向が設定でき、同じ命令でも動作が変わる
プログラムが明示的に設定しなければ、当然OSが設定した値になる >>223
こういうの見るといつも思うんだけど、全部Perl(など)で全部完結して書くのとどっちがいいのかな?
殊に「高速で」条件があるなら。 >>230
パイプ有利でしょ
なぜなら perl は C の 10% 程の速度
シェルスクリプトの基本ツールは C で書かれているから早い
そしてパイプは並列プログラミングだ 並列「プログラミング」ではないな
単に仕組みとしてプロセスが同時並行しているだけで >>230
どうでもいいけど
>>223は基本的なコマンドで完結してるシェルスクリプトなので
Perlで「全部完結する」というのは対比する表現としてはちょっとおかしく思えるな 単機能のコマンドを組み合わせて処理するのがシェルスクリプトだからな
それで速度が遅いだの言うならシェルスクリプトなんか使わなければいい >>223
uniq -cの前にsortしなくていいの? >>235
別のところで動かしたらだめだったよ
sort 必要 ソートはたぶん早くないから
つまりコストが高いから
たぶん定番のあれやったほうがいい
1行ずつ読みこんだそれでハッシュ作って インクリメントしてくあれ 実はPOSIX sortならsort -uでuniq | sortと同等ことができるのでuniqは実質要らない子 uniqは重複したのを抽出する目的での利用が多いな
純粋にuniqで使う機会の方が極端に少ない uniq | sortって使い方分かってない奴かよw
uniqくらいソース読んでみなよ >>240
そんな揚げ足取らんでも。。。
sort | uniqの間違いです。 ls .-lのrwxに8進数表記も追加できないかな あ、setuid/setgid/sticky bit のこと忘れてたわ find ~TEST -type f -printf "%h\n" |sort |uniq -c
これは早いわ duのファイル版は俺も作ったけど未熟なんでこんな出来に
find ./ -type d -printf "%p " -exec bash -c 'ls -b "{}" | wc -l' \; | sed -r 's/(.* )(\w+)/\2\t\1/g' >>207
Ruby の、1-liner で、特定のディレクトリ以下を再帰的にたどりながら(find)、
ディレクトリ以外(reject)を表示する。
%Q("〜") は、" を、Windows のPowerShell に解釈させないために、クォートする
-r で、pathname モジュールを読み込む
ただし、途中で改行しているけど、実際には改行しないで下さい!
ruby -rpathname -e 'Pathname( %Q("C:/Users/Owner/Documents/Ruby/test") ).find
{ |path| if File.directory?( path ) then; puts path, path.children.reject( &:directory? ).length end; }'
出力
C:/Users/Owner/Documents/Ruby/test
11
C:/Users/Owner/Documents/Ruby/test/a
4
C:/Users/Owner/Documents/Ruby/test/a/b
0 stat -c '%A %U %G %z %n' .*
↑こういうのどう? lsのパーミッション表示を8進数に
まあPOSIXに規定されてないけど >>245
sort を差し替えた
~/ 対象にしたら倍速
find ~/ -type f -printf "%h\n" | perl -ne '$dirs{$_} += 1; END{for $key (keys %dirs) {printf "%5s %s", $dirs{$key}, $key } }' 途中だった
最後に | sort -k 2,2 入れても入れなくてもあまり変わらない
やはり指数関数的にsort に大量渡すと遅くなる POSIX の find って -printf がないのな。
難しいことは -exec でなんとかしろということか。 >>252
perl の中で sort やれば良いのでは?
sort keys %dirs にして。 Perlようわからんけど、findのところもまとめていわゆるVisitorパターンでやると?
シェルだと時間掛かる。
#!/bin/bash
shopt -s dotglob
walk() {
local c=0
for p in "$1"/*; do
if [ -d "$p" ]; then
walk "$p" # recursive call
elif [ -f "$p" ]; then
((c++))
fi
done
echo "$1: $c"
}
start_dir=$(basename "$1")
walk "$start_dir" どうせPerl使うんならPerlに用意されているfindコマンド的な関数使えばいいのに。
いや正直Perl書けないので外部コマンドのほうが効率いいのかも知れんけど 今回たまたま perl が早かったのは
>237
ということ
つまり C は10倍ぐらい早いけど
何十倍も無駄なことやってたら遅くなってしまう
高速な find の出力を |sort |uniq -c したら一応答えでるけど
そのsort がウルトラ処理多い
だったらperl で1行ずつ読んで正しいアルゴリズムで処理したほうが早いだけ awk版。ディレクトリ名でソートするなら sort -k2
find . -type f -exec dirname {} + | awk '{c[$0]++}END{for(i in c){printf"%4d %s\n",c[i],i}}' | sort xargs使ったほうが良いかな
find . -type f | xargs dirname | awk '{c[$0]++}END{for(i in c){printf"%4d %s\n",c[i],i}}' | sort やってることが同じなら、Perlとawkは比較するまでもないのでは? 数分で書けるのがシェルスクリプトの良いところなんだし
数百万のファイルを何分以内で処理せよとか性能要件があるなら
そもそもシェルスクリプトなんかで書かないわ なんかシェルスクリプトを貶す人間ってシェルスクリプトを本来の目的とは違う方法で使った結果失敗して
その恨みを自分の無能さではなくシェルスクリプトにぶつけてる印象。 このパーツは意外と頻度多いからCで書いておいてもいいかもね
| perl -ne '$dirs{$_} += 1; END{for $key (sort keys %dirs) {printf "%5s %s", $dirs{$key}, $key } }' 端末の応答(例えば$ printf '\e]11;?\e\\'で返ってくる\e]11;rgb:〈赤〉/〈緑〉/〈青〉\e\\っていう文字列)を
sedやらなにやらで加工できるように標準出力に流したいんだど
そのままの状態だと端末そのものに文字列が渡ってしまって加工できない。
$ printf '\e]11;?\e\\' | od
みたいにすると(当然だけど)\e]11;?\e\\という文字列がパイプを通ってしまう。
個人的にはsttyとかをうまくやりくりしたらいけそうな気もするのだけど
そういう文書や記事がないのと俺があまり端末の処理に詳しくないのとで今のところ成功していない。
端末応答を標準出力として処理できる方法知らないですかね。 >>272
色というものが何者かわかってないんじゃね?
色を付けるためのエスケープシーケンスっていうのは、
エスケープ文字、ASCIIコード表でESC(0x1B)の文字8進数だと033
ESC文字から始まる一連の文字列の流れ(シーケンス)ってだけだよ
だから0x1Bで始まるその文字列を加工すりゃ良い。
\e]11;の ]11;は単なる文字だけど、\eは(シェルによりけりだが)
0x1Bの文字に置き換わる。だからsedなんかで\eを見つけようとしてもだめ
そんな文字列は流れてこないんだから >>273
あー。いやそうじゃなくて 端末の応答を取得したいんよ。
試しに
$ printf '\e]11;?\e\\'
ってやってみて。多分端末の上に
^[]11;rgb:0c0c/0c0c/0c0c^[\
みたいな文字列が表われる。
この文字列をtestコマンドの対象にしたりしたい。
でも普通の方法ではこの文字列は標準出力ではなく端末の上に直接出力されてるから
そういう加工ができない。 >>274
話の内容を単純化しよう。
文字の内容は今どうでもいい話だろ?
printf 'hogehoge' ってやってみたら
端末の上に、hogehoge って表示されるな?
それでこの文字列をどうしたいって? わかってない奴が話に絡んでいくなよ
文字列なんか関係ない
奴はttyの出力(もしくは入力)を横取りしてパスワードを盗みたいという話をしてる $ printf '\e]11;?\e\\' の話だろ? >>278
試しに
$ printf '\e]11;?\e\\'
ってやってみて。 >>276
パスワードだとしたら、出力には返ってこないから横取りもできないんじゃね
パスワード生で出力するようなアレでなければ >>280
だから入力って書いたじゃん
エコーバックやめるタイミングを捕まえて入力側をだな
まあいいや、俺も答え知らないしw >>274
そういうのが出る Terminalアプリ もあるし出ないのもある
Terminalアプリが出しているんでしょ、その エスケープシーケンスを Terminalの画面制御 のために
Terminalアプリの作りによるんじゃないかなあ、また、Terminalアプリで何か提供してなきゃダメなんじゃないかなあ
>281
そもそもは出力をだから出力で入力をは無理だな。エコーバックは今時はローカルではしてないんじゃね、パスワードを生で表示だろしw なんのエスケープシーケンスなのか知らずにだったが、OSC Operating System Commandつうのね。で、制御ではなくてリポート(情報)なのね
Teminalアプリは、それを相手(シェルプログラム)への入力として出力しているのでできそうか ls結果をテキストエディタで開いた時[0mだらけで焦った思い出
ANSIカラーコードって正規表現で消せるのかしら >>274
#!/bin/bash
result=''
printf '\e]11;?\e\\'
while read -s -N 1 -t 0.2 char
do
result="$result$char"
done
printf "%s" "$result" > hoge
試行錯誤中だけど、こんなんで取れてる >>275
その文字列はパイプで処理できるじゃん。
例えば
$ printf 'hogehoge' | sed -e 's/hoge/fuga/'
でも端末応答の文字列はそういう処理ができないのよ。
試してみると分かる。 >>286
すげえ!ありがとう!
なるほどなぁ。readコマンドで対処するのか……。
全然文字列が取得できなくて悩んでたからマジで助かったわ。 こんな感じかなぁ
$ stty -echo;printf '\e]11;?\e\\'; IFS=';' read -r -d '\' _ bgcolor;stty echo
$ echo $bgcolor
rgb:3232/3232/3232 あ、尻尾に ESC(0x1b) が付いてるから適当に削ってちょ >>290
末尾のESC \は端末が返す文字列の仕様だから問題ないと思う。
というか応答の形式が
ESC ] 11;rgb/3232/3232/3232 ESC \
↑こういう感じ。 シェルスクリプトでラムダ計算を実装するとしたらどんなインターフェースがいいんだろう。
lambda -x @ 'echo @ | tr "[A-Z]" "[a-z]"'
でもこれだとこの後に適用したい変数を持って来たときにlambdaコマンドの引数と見分けがつかなくなる…。 パイプつなげるのが普通だから
xargs とか
なんか {} みたいなのでこれまでのパイプの流れてきたのを表現する
コマンドがあったからそれでいいんじゃないか? >>292
何が問題なのかわからんけど、
1. ラムダ計算だとしてlambdaコマンドに引数なんているの?
2. 'echo なんたら' の前がlambdaコマンド引数、後ろがechoの引数でいいだろ?
3. 'echo なんたら' で区切れない場合、-- で区切るのがよくある実装方法
って言っておくよ >>293
そうそう。xargsみたいなのを妄想してるw >>294
例えばPython3のラムダ計算だと
(lambda x: x * x)(3)
みたいな形式じゃん。
キーワードlambdaをコマンド
変数宣言x:を、どんな変数を扱うかというオプション
(xargsで言う-I)
演算本体のx * xは被演算子
としてみた。 このラムダ計算は偽物だ。食べられないよ。
また明日来てください。僕が本当のラムダ計算をお見せしますよ。 シェルスクリプトでラムダ式ってどんな場面で便利なの?
普通に関数定義すれば事足りると思うんだけどな https://www.sejuku.net/blog/23677#lambda
> #lambda式を使わずに通常の関数を用いる場合
> def func(price,tax):
> return price + (price * tax)
>
> payment1 = func(100,0.08)
> print(payment1)
>
> #lambda式を用いる場合
> print((lambda price,tax:price + (price * tax))(100,0.08))
よくわからんのでコレをサンプル。
price?tax? シェルスクリプトにとって引数とは$1, $2,・・・固定なんだよな。省略かな?w
echo "$(lambda '$1 + ($1 * $2)' 100 0.08)"
イメージ的にはこんな感じか。少数の計算があるんでbc使わなきゃいけないので動くように直すと
lambda() {
formula="$1"
shift
echo "$(eval "$formula")"
}
echo "$(lambda 'echo "$1 + ($1 * $2)" | bc' 100 0.08)"
一発で普通に動いたわw
シェルスクリプトにとって戻り値=出力なんでこうかけるし、
あとbcの使いづらいのをどうにかすればこんな感じでかけるだろう
lambda 'calc "$1 + ($1 * $2)"' 100 0.08 bash の mapfile にある callback みたいなもん? 数値計算ならbcに直接渡すし
文字列を加工するラムダ式はbcで処理できないし
必要性を感じたことないんだよね >>304
すごいけど
数値計算に限定されるのが残念な仕様だね。 >>307
へ?数値計算に限定するならもっとシンプルに書けるよ
これだけにできる
lambda '$1 + ($1 * $2)"' 100 0.08
数値計算に限定してないから呼び出し側にechoとかbcが埋め込まれてるんだけど? lambda関数は>>304のままで小文字を大文字にする例
lambda 'echo "$1" | tr "a-z" "A-Z"' abc ラムダで用いる計算式は通常短くなるから、
$1, $2 であっても分かりづらくなることはないだろうが
もともとの人は変数をどうすべきかって言ってたから書くと
lambda 'calc "$1 + ($1 * $2)"' 100 0.08
は
lambda v1 v2 -- 'calc "$v1 + ($v1 * $v2)"' 100 0.08
ってやろうと思えばやれる。変数に入れてからevalすればいいだけだから
それが>>294で書いたこと。--で区切るのが面倒だと思えばこういう書き方もありだろう
lambda v1:v2 'calc "$v1 + ($v1 * $v2)"' 100 0.08
第一引数が:で区切られた変数名、第二引数が計算式、残りが引数と簡単に見分けられる 数値限定で引数全てに計算式を適用して返す例(笑)
map() {
formula="$1"
shift
while [ $# -gt 0 ]; do
eval "echo \$(($formula))"
shift
done
}
map '$1 * $1' 1 2 3 書き方が煩雑になるだけでメリットないんじゃね
やりたいこと素直に書けばいいじゃんって思ってしまう まあ、それはラムダ計算そのものが言われていることだからw
シェルスクリプトの話ではないね。 ラムダ式って簡潔に書けるのがメリットでしょ
コード量増えるのなら本末転倒だよね 簡潔に書けてるよw
map '$1 * $1' 1 2 3
ただ違うのはシェルスクリプトにはそれようのライブラリがないだけ
ここで例示したようなmapみたいなライブラリ集ができたら
もっと便利になると思う というか、普通の言語のラムダ式だと、こんな感じで変数が出てくるけど
lambda a, b : a + b
引数名が$1, $2と数字固定だから変数宣言が不要になるんだよな
lambda a, b : a + b がシェルスクリプトだと
lambda '$1 + $2' だけになっちゃう
i = (lambda a, b: a + b)(1, 2) はシェルスクリプトだと
i=$(lambda '$1 + $2' 1 2) こうなる クロージャの概念がないシェルスクリプトは
ラムダ式の真価を発揮する場面は無いだろうね 無いっていうのは出来ないんじゃなくて
用意されてないって意味だけどな
実はPOSIX標準でも一つだけクロージャーが使われてる。
それがtrap
trap 'echo trapped; exit 1' INT
みたいな書き方ができる ていうか(ほぼ暴論だけど)シェルスクリプトだってオブジェクト思考っぽいことはできる訳だし
単に「向いている処理」「向いていない処理」があるってだけ。
シェルスクリプトでラムダ式は書けるけど、シェルスクリプトはラムダ式を扱うのには向いていない。 そんな難しく考えるなよw
trapの例もあるんだし、使うのが適切な場合に使えば良いいんだよ map は意外と使い道がないんだよな
lisp 以外では意外と実装されていない mapがある言語
Python、Ruby、Perl、JavaScript、C#(LINQのSelect)
思いついたものだけ trapってただのイベントハンドラだよ
引数渡したり戻り値受け取ったりできないじゃん trapはイベントハンドラじゃない。
シグナルに対してイベントハンドラを設定するもの
引き数渡したり戻り値受け取ったり出来ないのは
trapの制限であってイベントハンドラの制限じゃない 言いたいのはクロージャの話してるのにtrap 持ってくるのは筋違いってことだ 別に筋違いでもない。戻り値は(標準)出力と上で書いたが、
trapで出力したものは画面に表示される。 「mapは意外と使い道がない!lisp以外では意外と実装されていない!!(キリッ」 正直>>321のmapの話は無知だなと思ったけど(めちゃめちゃ実装言語があるので)
そうやって煽ることしかできない君より100万倍有意義な発言だったよ。 >>329
本人乙。
勉強になったなw
次からはあんま調子乗らないよう気を付けろよ?ww 集合XからYに写像を持つ関数fがあれば
Y = f(X) と書ける
これを満たす x, yは
y = f(x) で表わせる
数学だとこんなかんじだが
プログラムなら
Y = map f X のような感じでいっきに変換できる
map 使わないで、古典的なループを書くと
for my $x (@X) {push @Y, &f(x)}
のような具合になるが、x, push など本来不要な変数や操作を中継するため
コードが肥大化する >>336
Y = f(X)って書き方は数学ではあんましねーな。
f: X → Yという風に書く。
ラムダ計算は
f: x ∈ X ↦ y ∈ Yに対して
(λ x ∈ X. y ∈ Y)のことを言う。
↑こうすると
f(x) = yっていう「普通の」関数適用が
(λ x. y)(x) = y
というように「f」という新規記号を用いずに表せる。
ここから>>336の後半に続く。 >>316
たしかにそう言われるとシェルスクリプトのほうが
短かいっちゃ短かいな。
変数名が固定されることが有利に働くとは。 >>339
perlのsortの場合、$a、$b固定になってる
https://perldoc.jp/func/sort
my @articles = sort {$a cmp $b} @files;
perlの場合、関数の引数は$_[0]、$_[1]で取れるのだが
そうすると、sortの外の$_[0]、$_[1]になってしまう。
文字列にしてevalしちゃえば同じことはできると思うがそれでも長くなっちゃうしな。
my @articles = sort '$_[0] cmp$_[1]' @files;
このために$a、$bをグローバル変数としているようだが、Perlはダイナミックスコープを
使えるからローカル変数にできるんじゃないかな? 互換性のためにそうなっているのかも >>336
一気に変換できるとありがたい例が
具体的に思いつかないのですか >>341
有り難いと言うか、記述が短くなったり、余計な変数を使わなくてよくなったり、連結して書けて分かりやすくなったりという利点があるかな。 >>341
集合を扱うのに適した型がない言語、perl などを例にすると
後ろの方を見るのに時間がかかる大きなリスト素早く参照するハックとして
>271
のようにハッシュに打ちこむ手法がある
シェルスクリプトのワンライナーだと1行ずつ入ってくるけど
perl コード内なら簡潔に書けるし、たぶん map の部分が C で書かれてて
速度が出ることが覆い
このタイプの高速な手法としてはシュワルツ変換が有名
|sort -k 2,2
に相当するやつ >>340
心配しなくてもその $a と $b はダイナミックスコープなローカル変数だよ。
レキシカルスコープでなければローカル変数じゃないという意見もあろうが。 >>344
リンク先にはグローバルって書いてある。
下の方にごちゃごちゃ書いてあるけど、ちょっと今読みたくないやw ていうかシェルスクリプトの関数って(少なくともPOSIXの範囲では)広域定義で
システムのコマンドと同じ名前空間(名前空間なんて一つしかないけど)で定義するしかない。
だからラムダ式に代表される無名関数は寧ろシェルスクリプトのような言語で重宝するかも知れない。
でも可読性や保守性を考えると一般的でない書き方なので多用は控えたほうがいいかな。 >>345
もちろんそのリンク先に書いてある。……下から 21 行目に。(空行を除く) シェルスクリプトで引数が整数であることを判定する可搬で高速な方法ってなんだろう
思い付いたのは
isint() {
case "$1" in
[0-9][0-9]*) printf '%d\n' $1 ;;
*) return 22 ;;
esac
}
…ところで$1がないときは標準入力から値を取得するっていう操作ってどう実装するんだろう? >>348
標準入力かどうかは
けっこうシェルスクリプトとperlは同じような書き方する部分があるから
こんな構文がありそうだ
https://pastebin.com/0wXLeenr
あとそれだと負の数が抜けてる。数字の前に マイナス記号がついている可能性がある case $1 in # $1にダブルクォートはいらない
*[!0-9]* ) ;; # 数字以外が含まれている = 整数ではない
*) ;; # それ以外 = 整数である
esac
if [ $# -eq 0 ]; then
read -r data
else
data=$1
fi
とかいろいろ > 数字の前に マイナス記号がついている可能性がある
case ${1#-} in
こうすればよい $1があるかどうかじゃなくて、echoなどで流し込まれているかどうかなら
if [ -t 0 ]; then
# 流し込まれてなどいない
else
# 流し込まれている
fi 所でcaseって戻り値を返すって知ってる?
isint() {
case $1 in
*[!0-9]* ) false ;;
*) true ;;
esac
}
if isint 1; then
echo int
fi
とか、
if case $1 in *[!0-9]* ) false ;; *) true ;; esac; then
echo int
fi
とか
if ! case $1 in *[!0-9]* ) false; esac; then
echo int
fi
とか書けるよ > if ! case $1 in *[!0-9]* ) false; esac; then
間違えたw !いらない
最短かな?
if case $1 in *[!0-9]*) false; esac; then
echo int
fi
ワンライナーw
isint() { case $1 in *[!0-9]*) false; esac; } あ、空文字のときにintになるね。こうすればよい
isint() { case $1 in ''|*[!0-9]*) false; esac; } expr "$1" + 0 >/dev/null 2>&1
echo $?
というのもありかと思ったけど、MAXINT(2^32or2^64)以上になると
エラーになる(exit status 3)からダメか みなさんありがとうございます。
↓助言を参考にさしてもらってこういう形にしました。
isint() { set -- "$1"
case ${1#-} in
''|*[!0-9]*) return 22 ;;
*) true ;;
esac
}
「$1が設定されていなければ標準入力を$1に」というのはシェルスクリプトでは
実現が難しそうなので諦めます。 if case $1 in *[!0-9]*) false; esac; then
echo int
fi
こっちのほうが短いかw
case $1 in *[!0-9]*) :;; *)
echo int
esac ……と思いましたが良い感じの構文を思い付きました。
isint() { set -- "${1:-"$(cat)"}"
case ${1#-} in
''|*[!0-9]*) return 22 ;;
*) true ;;
esac
}
これでどうでしょうかね。もし$1が設定されていなければcat(1)が実行されて
cat(1)には引数が渡っていない(この時は$1が設定されていない)ので
If no file operands are specified, the standard input shall be used.
(http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cat.html)
に従って標準入力が読み込まれてset -- 〈標準入力の内容〉となって$1に標準入力が設定される。 trueはさっき俺が書いたけど、別にいらない
isint() { set -- "$1"
case ${1#-} in
''|*[!0-9]*) return 22
esac
}
> 「$1が設定されていなければ標準入力を$1に」というのはシェルスクリプトでは
こっちも書いたはずだが? cat "$1" or cat "/dev/stdin" の話でもしてたのか? >>361
申し訳ないです。完全に見落してました。 npmでシェルスクリプトだけのパッケージを配布してもOKですか? >>361
catとreadってたった一行読み込むのにそんな差ある? sedで質問です。
置換前
(a0b1c2=99999) (a0b1c2=00000)
置換後
DATA1=99999 DATA2=00000
こんな感じに置換したいです。
カッコと接頭辞みたいなのを除去した上で、
行の1つめはDATA1に、2つめはDATA2に置換したいという意味です。
何卒ご教示ください。 (
[a-zA-Z0-9]
=
[0-9]+
)
こんな形のデータか? 暫定これ
echo "(a0b1c2=99999) (a0b1c2=00000)" | sed -n 's/([a-zA-Z0-9]\+=\([0-9]\+\)) ([a-zA-Z0-9]\+=\([0-9]\+\))/DATA1=\1 DATA2=\2/gp'
DATA1=99999 DATA2=00000 >>370
すいません、話を簡単にするため>>369は端折ったんですが、
端折らない方がよさそうなので元データそのまま書きます。
わかる人にはわかるかもしれませんが、VMwareのAPIから取ってきた値です。
guest(01) %!s(int32=110) %!s(int32=3625)
これは左からゲスト名、各ゲストのCPU使用量(MHz)、メモリ使用量(MB)です。
これを
guest(01) CPU=110 Memory=3625
こんな感じにしたいなと思っています。
最初はsedの単純な置換とパイプで何とかしようとしたんですが、
ゲスト名にもカッコが使われてる(のが除去されちゃう)という部分が回避できませんでした。 echo 'guest(01) %!s(int32=110) %!s(int32=3625)' | sed -n 's/\S\+([a-zA-Z0-9]\+=\([0-9]\+\)) \S\+([a-zA-Z0-9]\+=\([0-9]\+\))/DATA1=\1 DATA2=\2/gp'
guest(01) DATA1=110 DATA2=3625
これで間にあう? 失礼しました
最後のCPU, Memoryに書きかえて
echo 'guest(01) %!s(int32=110) %!s(int32=3625)' | sed -e 's/\S\+([a-zA-Z0-9]\+=\([0-9]\+\)) \S\+([a-zA-Z0-9]\+=\([0-9]\+\))/CPU=\1 Memory=\2/g'
guest(01) CPU=110 Memory=3625 >>361
パイプにテキストファイルの中身を流し込んで逐次処理するとき、
cat "hoge.txt" | 〜 のほかに、
echo $(< "hoge.txt") | 〜 とか、
lessなどのページャー読み込みでもできるけど、
どうするかいつも悩むなぁ。
grepなどの、ファイル読み込みオプションのあるコマンドが先頭ならそれを使えばいいけど、
そうでない場合は、みんなどうしてる? >>375
何故 < hoge.txt じゃ駄目なの? >>374
できました!ありがとうございます!
高度すぎて何やってるのかさっぱり理解できてませんが、
じっくり解読させていただきます。 >>376
複数のパイプを繋げた逐次処理の場合に、
処理元のファイルが何であるかを明確にしたいので、
すべてのパイプの先頭に持っていきたいんだよ。
ファイル読み込み | 処理1 | 処理2 | 処理3… 俺なら
< hoge.txt cmd1 | cmd2 | cmd3 ...
と書く >>379
ほぉ、リダイレクトって、コマンドの前にもってこれるんだ。ありがとう。
これならとりあえず、ソースを明確にできるね。
しかもおそらく一番処理が速いかな。
catを使った方法のような、単に読み込むだけのコマンドの高速版みたいなのはないのかなぁ。 >>377
正規表現は実行可能な回戦ノイズになりやすいから、
複雑なものは、可能なら perl を薦める
バックスラッシュの頻度も下がり、空白で単位ごとに分けられ読みやすい
echo 'guest(01) %!s(int32=110) %!s(int32=3625)' | perl -pe 's{ \S+ \( [a-zA-Z0-9]+ = ([0-9]+) \) \N{SPACE} \S+ \( [a-zA-Z0-9]+ = ([0-9]+) \) }{CPU=$1 Memory=$2}xg'
guest(01) CPU=110 Memory=3625
sedの正規表現にはいくつか注意すべきことがあると思う
match部の
( が 文字どおりの ( にマッチする
\( が あとで \1 \2 で使う為のキャプチャの括弧になる。
\+ が1つ以上の という個数指定になる ……Perlも十分読み難いと思うのは俺だけだろうか… perl が使えるような環境なら sed -E 使えるんじゃね? >>382
もっと分かりやすそうに書いてみた
今度はどうだ?
echo 'guest(01) %!s(int32=110) %!s(int32=3625)' | perl -pe ' $pattern = q{ \S+ \( [a-zA-Z0-9]+ = ([0-9]+) \) } ; s/$pattern \N{SPACE} $pattern/CPU=$1 Memory=$2/x'
guest(01) CPU=110 Memory=3625 >>384
$pattern への値の代入は一回で良いので BEGIN { ... } の中に入れた方が効率が良くなる。
(勝手に最適化されて最終的には大差なくなってしまうかも知れないけどね)。 これぐらいのの複雑さになると、perl でちゃんと改行、インデントして
書いた方がいいような気がする シェルスクリプトは関数型だとかアホなこと言ってるブログがあった Ruby では、
def get_value( str ) # = ) の間にある文字列を取得する
pos_1 = str.rindex "=" # 文字を末尾から探す
pos_2 = str.rindex ")"
str[ pos_1 + 1 ... pos_2 ]
end
str = 'guest(01) %!s(int32=110) %!s(int32=3625)'
ary = str.split # 空白で区切る
# ["guest(01)", "%!s(int32=110)", "%!s(int32=3625)"]
puts "#{ ary[ 0 ] } CPU=#{ get_value( ary[ 1 ] ) } Memory=#{ get_value( ary[ 2 ] ) }"
# guest(01) CPU=110 Memory=3625
1-liner では、
ただし、途中で改行したので、1行にしてください!
echo 'guest(01) %!s(int32=110) %!s(int32=3625)' | ruby -ne 'def get_value( str ) pos_1 = str.rindex "="; pos_2 = str.rindex ")"; str[ pos_1 + 1 ... pos_2 ] end;
ary = $_.split; puts "#{ ary[ 0 ] } CPU=#{ get_value( ary[ 1 ] ) } Memory=#{ get_value( ary[ 2 ] ) }"' 上の方の数値判定だけどマイナス記号を考えない(つまり正整数だけを判定する)のなら
[ ! ${var%%[0-9]*} ]
これが最速で(記述も)最短じゃなかろうか。 >>390
シェルのパターンマッチングでの '*' って any string の意味なので、
$ var='10abcdefg'
$ [ ! ${var%%[0-9]*} ] && echo integer
integer
となってしまう。bash の extglob を使うなら、
$ [ ! ${var%%?([-+])+([0-9])} ] && echo integer
などと書ける(空文字の場合に対応してないけど)。 >>392
おうマジだ。
なぜか英字のみと数字のみの変数で試してたから気付かなかったw
恥かしすぎるw 突飛なことはせずcase分使うのが一番いいのかな。
正直、俺だったらそもそも「型」の概念が必要になるようなプログラムは
シェルスクリプトで書かないけど * は、シェルスクリプトでは、0文字以上の任意の文字列で、
正規表現では、直前の文字の0回以上の繰り返し
正規表現を使うのなら、egrep, grep -e でフィルターしないといけない
egrep '正規表現'
これもシェルで解釈されないように、シングルクォーテーションで囲む方がよい perlは正規表現しか知らんが構文は結構読みにくいのね
pythonやruby辺りやった方がいいのかな
簡単なシェルスクリプトを書いたりsedやawkで弄ったりはしてるけど シェルスクリプトとしてはワンライナーが短く書け、
カオスも含めた無限のような表現力のあるperl を薦める
seq 30 | perl -0777 -ne 'print $_ =()= /1/g'
13 seq 30 | tr -dc '1' | wc -c
でいいんじゃね >>397
>>398
この二つって1から30までの間に何回1が登場するかを数えてるの? Ruby では、1 の個数を数える
seq 30 | ruby -e 'puts ARGF.read.count( "1" )'
#=> 13 何の意味があんの?
Perlだと複雑に書けるよってこと? 1 を数えたいなら
$ seq 30 | grep -o 1 | wc -l きっと見たこともない構文だと思って書いた
しかし、ここに多く書かれるより短いワンライナーより長いので
全然良くなかった
本当は「普通は思い浮かばない書き方の中に
短く書けるような可能性がある」と思わせたかったけど
力不足だった PowerShell では、
$matches = 1..30 | Select-String "1" -AllMatches
$matches.Matches.Count
#=> 13 PowerShellって嫌われてるけど結構便利だよね。
でも使い熟せる自信も気力もないw PowerShellってどういう場面で使われるの?
Bash使わないでPowerShell使うことってあんの? windows update からの shutdown
でも十分便利そうだ
UIがことごとくGUIだから
砂漠の水のように利くんじゃないか? Remove-Item、Copy-Itemとか生理的に受け付けない体になってる。 >>413
簡単にWebを検索してみてそれらしい記述を一件のみ見付けた。ほんとにこれがdoshの由来かは知らん。
OpenSolarisのBシェルから派生したSchily Bourne ShellというUnixシェル
http://schilytools.sourceforge.net/bosh.html
によると
* dosh builtin that allows to implement parametrized aliases.
らしい。 >>418
サンクス。boshなんてのがあるのか。
でもなんとなくboshが最初だとは思えないな
POSIXに影響を与えてるぐらいだからもっと大きな元ネタがありそうだけど
あとなんの略かもわからん。まさか do sh (shする?)
あと>>413のリンクが間違っていたので訂正
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01 ここには元ネタはUNOSとか書いてあるね。
https://unix.stackexchange.com/questions/453827/making-alias-of-rm-command
This concept of parameterizable aliases has been invented by former AT&T
employees in 1980 and implemented in their real time UNIX clone called UNOS. https://www.in-ulm.de/~mascheck/bourne/
> built-in "dosh" added, behaves similar to "sh -c 'command'" without launching a new shell, supports aliases
あぁ、なるほど。sh -c 'command'と同じように使えて
新しいシェルを起動しないから、do sh なのか https://unix.stackexchange.com/questions/145522/what-does-it-mean-to-be-sh-compatible
If you like to know more relations, e.g. with UNOS "command", "bsh" and the recent
Bourne Shell, send me a note. As a hint: UNOS command had a builtin command
"do" that acted as a one-line shell script with arguments. This idea was transferred into
the Bourne Shell as "dosh" and permits parameterizable aliases, something you cannot get from ksh or bash. ? schily
このschilyってのはSchily Bourne Shell(=bosh)の作者かな? >>423
この回答者>>419じゃない?
そうだとしたら確実にOpenSolarisのシェルに携わってる人。 「OpenSolarisのシェルに携わってる」はちょっと疑問かな
http://schilytools.sourceforge.net/bosh.html
> The Schily Bourne Shell was derived from the Bourne Shell sources from OpenSolaris.
と書いてあるように、OpenSolarisのシェルをベースに改良したSchily Bourne Shellの作者のようだ。
OpenSolarisシェルそのものには関わってない気がする
Schily Bourne Shellには、古いBourne Shellと互換性があるoboshと
POSIX厳格なpboshと、POSIX準拠+拡張のboshの三種類のシェルが含まれていて、
そのboshにはOpenSolaris Bourne Shell にはない機能
> The enhanced Schily Bourne Shell (bosh) implements the following features that are missing
> in the OpenSolaris Bourne Shell listed above:
として、自身が昔仕事で関わっていたUNOS
https://unix.stackexchange.com/users/120884/schily
> First paid UNIX related work with UNOS in 1982.
で実装されていたdosh(元はビルトインコマンドの"do"?)を移植したという流れっぽい。
だからSolaris Bシェルの手引書には無くて当然なのだろう。
Bourne Shellにも移植された
> This idea was transferred into the Bourne Shell as "dosh"
ようだから、どこかの実装にはdoshが存在するのかも >>425
ははーん。そういうことか。
Solaris Bシェルが持ってた拡張機能じゃなくてSolaris Bシェルに対する拡張機能だった訳ね。
Solarisの手引書を漁っても見付からない訳だ。 全然関係ないけど
$'\n'←こういうのって2020年あたりに発行されるPOSIXに組込まれるかもしれないらしいね。
そのページの下の方に書いてあった。
互換性とか大丈夫なのかな……? 参考: http://austingroupbugs.net/view.php?id=249
ていうかAustin GroupってThe Open Groupとは別ドメインなんだな。
サブグループだと思ってたわ。 >>414
get-alias (gal)で、alias を表示できる。
多くのLinux コマンドのalias も、指定されている
gal | where-object {$_.Definition -match "remove-item"}
# Remove-Item のalias は、del, erase, rd, ri, rm, rmdir
gal | where-object {$_.Definition -match "copy-item"}
# Copy-Item のalias は、copy, cp, cpi
gal -name ls
# ls -> Get-ChildItem
gal -name echo
# echo -> Write-Output >>429
それ日本語が出てるの?
それとも日本語はあなたが付け足したの? >>412
お釈迦様のアドバイス「犀の角のように独り歩め」も意味わからん… >>432
Debian 9で普通にmakeしたらできたけど?
正確にはDockerのbuildpack-depsだけど おや?最新版、2019-07-22版でビルド失敗した。
なんとなしにNetBSDでパッケージがあるのを見つけて使った2019-03-11版が運が良かったか
https://cdn.netbsd.org/pub/pkgsrc/current/pkgsrc/shells/bosh/README.html 2019-06-13までは普通にビルドできるね
2019-07-15からビルドに失敗するようになってる >>435
情報ありがとう。古いので試してみるわ。 関数の中は、set -eで止めたいけど、関数の外では(後処理をするために)止めたくないって場合が辛いわ
例えばこんなコードがあって、falseで止まるようにしたいからset -eにするだろ?
foo() {
set -e
echo 1
false
echo 2
}
でも呼び出し側では必ず後処理をしたいから止めたくない。
set +e
foo
echo "後処理"
これだと止まってしまうから、foo &&: とかすると
今度は、fooの中でset -eの効果が無くなってしまう。何だこの仕様?
( foo ) とすると期待通りにfalseで止まるかつ後処理を実行できたが、
fooがサブシェルなので、fooの中で定義した変数にアクセスできない
困った >>431
それは犀の角が一本だからという、特にひねりのない喩え。 set -eはshellをexitするから当然の動作じゃない?
foo && : だと最終的なfooの戻り値を判定する必要があるからfalseで止まらずに最後まで行くんじゃないか
関数の中だけなら横着せずに
false || return
しろってことじゃないかな 後処理だけなら、trap '後処理' ERR でやれば
根本的に -e の使い方が違うと思うけど $ dash
$ trap : ERR
trap: ERR: bad trap どうやってEXITから終了せずに通常の流れに戻すの? func() {
return 123
}
if ! func; then
echo $?
fi
0って表示されるんだけど、どういうこと!? >>446
戻り値123を!しているから0になっただけでは こう書けってことか?
面倒くさいな
if func; then
:
else
echo $?
fi んじゃ、
func || { echo $?; ... ; }
とか。 Cじゃないから終了コードをそんな風に使わないほうが良い気がする…
あくまで「気がする」だけだけど 値が 0 とそれ以外だけではなく、
それ以外にも、ある程度数値に意味があるのもあるからいいんじゃないのと思うけど ああ、そんな風 = 返り値が勝手に暗黙的に変わる変わらないってことかな?
だったらほぼ同意 >>453
あー。例えばあるコマンドで「ファイルが無い」ことを示すのに
exit 32が返ってくるとして
それに応じた最適なエラー処理をするってことかな? まあ元レスの人がどういう使い方をしたいのかわからんけど、そういう感じ bcコマンドで階乗計算をしたくてコードを書いてるんだけど↓
n = 2
define f(n) {
f = 1
if (n == 0) { return(f) } /* 0! := 1 */
f = n * f(n - 1)
return(f)
}
"0! = "; f(0)
"1! = "; f(1)
"2! = "; f(2)
"5! = "; f(5)
多分これでいい筈なんだけどreturn式を二度使ってるのがダサく感じる…
もうちょっと賢い方法知らない? define f(n) {
if (n == 0) {
f = 1
} else {
f = n * f(n - 1)
}
return(f)
}
とか( n < 0 の場合、無限ループになるけど) elseはGNU拡張
else使えないならこうするしかない
define f(n) {
if (n == 0) { f = 1 }
if (n != 0) { f = n * f(n - 1) }
return(f)
} >>438
それ喩える意味あるぅ?
情報量低すぎるどころか混乱を招いて逆効果だわ。
「グーはチョキに勝つ。そう、斧が槍に強いように」とか言われてる気分。 世の中には例え話を持ち出さないと気が済まない人が一定数存在する。 >>462
知らんけど昔の人が思い付いていいと思ったから書いたんだろう。 >>190 WindowsにJavaが入るかもって話あったの?そもそもそんな話すらなくね? >>465
昔あったっしょ
Microsoft J++だったっけ?
JDirectとか言うCOMかActiveXコントロールかを直接呼び出せる機能拡張付きで、
それにSunがケチを付けて(確か)裁判沙汰になって、結局廃止になったやつ
TCKにも通らないだろうからJavaは名乗れないはずだけど 「マイクロソフトが Java に塩を混ぜた!」ってやつか sedかなにかで↓
<td>
AAAA
</td>
<td>
BBBB
</td>
↑っていうデータのBBBを取り出したい。
残念なことにtdにIDやらなにやらが賦与されてないから手段としては
「1番目に表われた/<td>/<\/td>/は無視って2番目の/<td>/<\/td>/の中身を表示する」
っていうのになると思う。しかし方法が思い付かない……。
できればsed, awkあたりで処理できればいいなと思ってるんだけど,どなたか力を貸してほしい。
上のデータだけど,「実際はもっと複雑でtableが入れ子になってる」とかそういうことはないです。 今までのレスからはそんな質問するはずがないとしか思えないんだけどw
<td>AAA
</td>
<td>
BBB</td>
なんぞリターンがあってもなくてもいいというhtml/xmlらしく、行がちゃんとしているわけではないとか? >>469
俺ならシェルスクリプト使わずにHTMLパーサに食わせるな
nodejsでcheerio使うとか楽な方法を選ぶね GNU sed の -z オプションを使って
$ sed -rz 's:.*</td>\n?<td>\n?(.*)</td>.*:\1:' data.html >>472
そうです。相手はHTMLなんで改行されてない場合が普通にあるんです……。
つくづくUnixツールとマークアップ言語は相性悪いなぁと思いますw GNU grep ならこんな感じ
$ grep -Pzo '<td>\n?\K(.|\n)*?(?=\n?</td>)' x.xml | tr '\0' '\n' | sed -n 2p >>476
すげぇ!
ありがとうございます!とりあえず脳死状態でコピペさせていただきます。
正規表現の勉強しないとなぁ……。 正直、CLIツール使って一発でやってしまおう!
なんて考えるから難しくなるんだよ。
一行一データになってないものは、
シェルスクリプトでやったほうが楽
#!/bin/sh
a=$(cat html.txt)
a=${a#*<td>}
a=${a#*<td>}
a=${a%%</td>*}
echo "$a" >>475
>を>\nにして\n\nを\nにすればいいだけじゃないの? Ruby なら、すべての改行を削除してから、最短マッチ
str = <<"EOT"
<td>
AAAA
</td>
<td>
BBBB
</td>
EOT
str.delete!( "\n" ) # すべての改行を削除する
re = /<td>(.*?)<\/td>/ # ? は最短マッチ
p results = str.scan( re ).flatten
# ["AAAA", "BBBB"]
p results[ 1 ]
# "BBBB" >>480
残念ながらそのHTMLは整形形式じゃないのでマトモに解析できないんです。 Ruby で、nokogiri パーサーなら、
require 'nokogiri'
doc = Nokogiri::HTML( <<EOT.delete( "\n" ) ) # すべての改行を削除する
<td>
AAAA
</td>
<td>
BBBB
</td>
EOT
elements = doc.css( "td" )
p elements.first.content #=> "AAAA"
p elements[ 1 ].content #=> "BBBB" >>476
\Kじゃなくて(?<=..._)で書いたほうが読みやすくね?とか思ったけど
PerlやPCREじゃlookbehindに可変長になるパターンは指定できないのか
JavaScriptだと通るんだよね.... Ruby遅すぎるんだよ
$ time ruby html.rb
"AAAA"
"BBBB"
real 0m0.079s
user 0m0.079s
sys 0m0.000s
$ time sh html.sh
BBBB
real 0m0.002s
user 0m0.002s
sys 0m0.000s これも遅いな。やっぱりシェルスクリプトが一番か
$ time grep -Pzo '<td>\n?\K(.|\n)*?(?=\n?</td>)' x.xml | tr '\0' '\n' | sed -n 2p
BBBB
real 0m0.003s
user 0m0.004s
sys 0m0.003s こうしたらさらに速くなったわw
シェルスクリプト最強伝説
#!/bin/sh
a="
<td>
AAAA
</td>
<td>
BBBB
</td>
"
a=${a#*<td>}
a=${a#*<td>}
a=${a%%</td>*}
echo "$a"
$ time sh html.sh
BBBB
real 0m0.001s
user 0m0.001s
sys 0m0.000s >>487
スクレイピングする時にそんなコード毎回書くわけ? a#*
a%% あたりがシェルスクリプト独自の難読パーツだが
覚えたら高速なのか... >>489
どっかの書籍(確かオライリー)に
数字を考えて#は数字の前に,%は数字の後に付ける。
という連想から
#及び##は前から削る,%及び%%は後から削ると覚えるといいと書いてあった。 自分は
キーボードの左側: # -> prefix
キーボードの右側: % -> suffix
で、削るんだっったっけ?残すんだったっけ?
結局毎回調べるという体たらく >>482
ブラウザでF12キーでコンソール開いて、
var q = (xml, query) => new DOMParser().parseFromString(`<xml>${xml}</xml>`, 'application/xml').querySelector(query).innerHTML.trim();
var text = q(`
<td>
AAAA
</td>
<td>
BBBB
</td>
`, 'td:nth-of-type(2)');
console.log(text); //=> BBBB
xmlとしてのパースだから、
q(`<chinko>AAAA</chinko><chinko>BBBB</chinko>`, 'chinko:nth-of-type(2)');
とかでも大丈夫。
一方htmlとしてもパースできるけど少なくともtableタグは補わなきゃならんね↓
var q = (html, query) => new DOMParser().parseFromString(html, 'text/html').querySelector(query).innerHTML.trim();
var text = q(`
<table>
<td>
AAAA
</td>
<td>
BBBB
</td>
</table>
`, 'td:nth-of-type(2)');
console.log(text); //=> BBBB >>490
> 数字を考えて#は数字の前に,
あー、ナンバーサインか
俺は、コメントだから頭につけるって覚えてたわ
%は同じく100%の%で後ろって覚えてたけど >>494
俺含め日本人には#42みたいなのは馴染み薄いよね…
まあ「全く知らない概念」ではなかったから
とりあえず#は前,%は後,というように覚えられたけど。
コメントっていうのはいい案だと思う。
シェルスクリプトを書いている全員が把握できる概念だから。 ナンバナィン?
#はスーパーユーザで%はcshだな シェルスクリプトの#と%はなんとなく使えてるが正規表現の前後読みは未だに無理ポ 正規表現の割と新しめの拡張は
既存のメタ文字と被らないようになってるから類推しにくい記号になってしまってる場合が多い。
…まあ出典とかなくて俺の予想だけどw
最近だと「名前空間」的な概念が登場して\p{Kata}みたいな書き方が増えてきて助かる。
覚えるの簡単! なんのこっちゃと思ったら.NETか
[:Katakana:]でいいんじゃないか。すでにあるからわかりやすいし
思惑でそうしてないんだろうけど >>499
いや\p{Kata}っていう正規表現が使えるのはかなり広範な言語よ
少くともICUバインディングがあれば使える筈。 逆に.NETでUnicodeロケールの正規表現が使えるとは思いもよらなんだ ...| perl -pe 's{" [^"]+ "}{ $& =~ s/ /-/gr }xeg'|...
awk でもできるかもしれないけどこの正規表現が便利
"text with blank space" の中だけ空白を-で詰め物するのに使っている
空白があると正常に動作しないコードの前パイプに挟む >>502
なんかコマンドの引数の仕様とかを利用して
POSIXの範囲で実装できそう。
もちろんperlで十分だけど。
abc def "text with blacket" dee
に対して
abc def "text-with-blacket" dee
ってい出力を返す訳だから
for str in abc def "text-with-blacket" dee; do
printf '%s\n' "$str" | tr ' ' '-'
done | tr '\n' ' '
とか?
あ,駄目だこれだと"が戻ってこねーw 無理やり
echo 'abc def "text with blcket" dee' |
sed -E 's:^(.*)"([^"]*)"(.*)$:printf "%s\\"%s\\"%s\n" "\1" $(echo "\2"|tr " " "-") "\3":e' $ echo やまだヤマダ山田 | grep -oP "\p{Katakana}"
ヤ
マ
ダ
-o使うと改行されるのね スペース区切りでよければ
$ echo やまだヤマダ山田 | grep -oP "\p{Katakana}" | xargs
ヤ マ ダ >>485
何百ページもパースするの?
Ruby でも十分早いと思うけどなあ 俺だったらperl使って全部読んで長い一行として扱って抜き出すか、または XML::Simple モジュール使って変数に展開してから取り出すかするかな。
つまり、シェルスクリプトは使わない。やってやれないことはないと思うが複雑怪奇なものになりそうなので。 あ、リロード忘れて書いたら山盛りで他の書き込みが・・・
俺の書いたことは忘れてくれ。 PythonのBeautifulSoupだと、パーサーにCで書かれたlxmlを選べるようになってるんだが、
そういうの使えば、シェルの方が断然速いとはならないんじゃないかな?
PerlとかRubyにも似たようなのはあるでしょ。 ディレクトリに、test01 〜 test99 ファイルがある時に、
test100, test101 と、ファイルを増やしていくと、
表示順が、test20, test21 などよりも、
test100, test101 の方が、先に来るようになった
これらを数字順で表示するには、どういうフィルターを作れば良いでしょう?
まあ、すべてのファイル名を、test001 など、3桁表示に変えれば、解決するけど >>515
プレフィクスが一緒なら
そのプレフィクスと0パディングを切り取ってsortに掛ければいいんじゃないかな。
で並び換えたものにプレフィクスと%0dを追加する。
ファイル名じゃなくてすまんが↓こんな感じ?
$ <<. sed 's/test0*//1' | sort -n | while read line; do printf 'test%02d\n' $line; done
test99
test100
test21
test01
test20
test101
. 改良。あとsort -nって0埋め関係ないんだな。
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html#tag_20_119_04
ls -1 test* | sed 's/^test//' | sort -n | xargs -I @ printf 'test%02d\n' @ >>515
GNUのsortなら-Vオプションがあるけど...
ls | sort -V
あるいはtest[0-9]*のファイルだけなら
ls | sort -t t -k 3n
とか(汚いけど) >>515
GNU coreutils の ls コマンドなら -v オプションで version sort してくれる
$ ls -v test*
$ man ls
-v natural sort of (version) numbers within text >>518
GNUのsort、-V オプション
ls | sort -V
これは便利! sort --help には
-V, --version-sort 自然な (バージョン) 数字順でソートする
って書いてあるけどさ、これセマンティクスバージョニングでの
比較にちゃんとなってるの?正確な仕様がわからん bashごと持って行けばいいんじゃね?
他のインタプリタ系の言語ってみんなそうしてるっしょ? >>526
馬鹿だなぁ。sortはシェルスクリプトじゃないよ。
sortコマンドだよ。可搬性がないのはsortコマンドだよ。
シェルスクリプトで実装すれば可搬性があるよ sortは-hもよく使うな
du -hc * | sort -hみたいに >>527
sortコマンドはBash組込みコマンドじゃないから関係ないんじゃ… busyboxをスクリプトに同梱して、
全部これに解釈させればいいじゃん
ashに加えて、よく使うコマンドも一緒についてくる いいじゃんと言われても…いいね。としか答えようがないw exitコマンドってexit $?とやってやらなくても前に実行したコマンドの終了コードを見てくれるんだな。
ずっとexit $?ってやってたわw if $? でやるより
&& || で分岐したほうが らしい 感じにならないか? >>534
ああいや。
埋め込みシェルスクリプト(←なんて呼べばいいのか知らんけど
実行形式のファイルで冒頭に書かれてることがある
そのファイル自身を伸長するシェルスクリプトのこと)
で使ってたのよ。
#!/bin/sh
< "$0" sed -n '5,$p' | unar -
exit $?
こっからZIP
↑みたいに。 tputの存在理由はわかるが
現実的な問題として、どういう場合にtput使ってよかったって思える?
もうエスケープシーケンス決め打ちでよくね? clearコマンドがPOSIXで定められていないのをいいことに実装されていない環境がある。
そのときにtput clear。 > 実装されていない環境がある。
「現実的な問題」っていうのはその実装されてない環境なんて、
今どきあるの?って話なんだよ。 clearが実装されてない環境より
tputが実装されてない環境のほうが多くて、
tputを使うと逆に動かない環境の方が多くなっちゃう
例えばbusyboxとかalpine linuxとか which clear >/dev/null 2>&1 && echo has || echo 404
両対応書いておけばいい /usr/share/terminfoの中を見てみたが、
シンボリックリンクを抜かして1700ものファイルがあった。
なるほどこれは大変だ。だがその中でどれだけのものが使われているのだろうか?
またどれだけ違いがあるのだろうか?ほとんどは細かい(殆ど使われない)
機能の違いでしか無いのではないか?
大抵は色を変えるぐらいしか使わないだろうし、
それ以上使っても画面サイズとカーソル移動ぐらいだろう。
数パターンしか違わないのであれば、独自対応も可能だろう。
実用レベルで考えるとtputを使うことは、使わないよりもデメリットが大きい気がしている。 vt100, xterm 以外設定した覚えがないな おそらく端末名の後ろは細かいバリエーションだろうからと削ってみたら789種類にまで減った
それでも数が多すぎるかつこんなの誰も使ってないやろと思ってしまって
何が違うのか把握する気が起きないレベル
でもinfocmpとか便利だな。よし俺の中で方針が決まった。
もしこれらの端末に対応しなければいけない自体になったら、
プログラムで直接tputを使用するのではなく、tputと同じ引き数で関数を実行しますから、
それで出力するエスケープシーケンスは設定ファイルで書き換えられるって方式にしよう。
さしあたって、現状、色を変えるだけしかやっとらんのだがtput使う必要あるのかな? なんであるものを使わないんだろう
二段階認証おじさんみたいな頭の構造なんだろうか > なんであるものを使わないんだろう
書いたでしょ? tputコマンドがない環境が現実としてある。 簡単なスクリプトを書いて、とりあえずcolsについて
データベースに登録されてる1700端末をすべて調べてみたが
すべてが 0x31 0x33 0x31 0x0a だった
boldだと非対応を除いて892端末。44パターン。結構違いがあるな
setafだと340端末、11パターン
まあtputを使うほうが楽だってのはわかるけど、エスケープシーケンスが違うのは
マイナー端末だろうし、数の割にパターン数は限られているので
完璧を求めたいなら別だけど使う環境で動けば良いわけで、tputを使用するのは過剰な気がするな。 む、/lib/terminfo/ 以下にも定義ファイルがあるのか
xterm-256colorがないのに使えると思ったら
まあ +40個しか変わらんけど シェルスクリプトマスターの皆様
xxxxNN.txtというファイルが大量にあります(xxxxの部分はファイル名、NNの部分は0〜99の連番)
NNの部分が50未満ならxxxx50.txtにNNが50以上ならxxxx99.txtに一括でリネームしたいのですがやり方教えてください xxxx の部分はファイルによって異なるって前提でOK? 無理に頭の体操的なことをせずに、こんな感じでいいでしょ?
for file in *; do
name=${file%[0-9]}
name=${name%[0-9]}
num=${file#$name}
[ $num -lt 50 ] && num=50 || num=99
mv "$file" "$name$num"
done >>555
ありがとうございます
早速試してみます! 早速試すとか言ってるが、
適当に書いたからどうなっても知らんぞ。 >>552
ファイル名に数字がまざってなければ
例ば[a-zA-Z]だったら
dry run は
| perl -pe 's{ \d+ }{ $& < 50 ? 50 : 99 }ex' ほとんど気にすることないと思うんだけどさ
みなさんが今まで携わってきたシステムでshが/bin/shにないシステムってあった?
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap10.html
ここによると/bin/shは既定されてない→つまり必ずしもあるとは限らない
みたいなんだけど、そんなシステムあるかね?
Solarisとかなら…と思ったけど/bin/shだったし。 Androidには/bin/shがないとか聞いたことあるな Androidはそもそも/binも/usrも無いな
mkshが/system/bin/shにある Androidの環境ってよくわからん。
busyboxは採用して無くて、昔はtoolboxだったのが今はtoyboxを採用している。
しかしtoyboxのシェルであるtoyshは完成して無くてmkshを使っている。
という理解であってるんだろうか?
dockerfileないんかな? Androidはヘッドレスでは立ち上がらんのじゃね?
昔見た限りだとinitスクリプト中でコケるんじゃないかと diffみたいに二つのファイルを開いて、一行ずつ交互に比較できないかな?
bash依存禁止で diff のアルゴリズムは有名だから
あとはもっと具体的にどうさせたいのかによりそう paste コマンド使うとか。見づらいけどw
$ paste -d '\n' file_a file_b 一旦質問を忘れて
同時に二つのファイルを開いて処理したい 他のスクリプト言語を使う方が幸せになれる様な気がする >>568
こんな奴に誰が答えたいと思うだろうか? POSIXシェルのみで全て書くという縛りプレイが好きなんだろうw
POSIXは最低限のインターフェースを規格化しているだけで、結局はプラットフォーム別に書くしかないのが現状だからな
bashがあるならbashで書けばいい
GNU拡張が使えるなら使えばいい
あるもんは使えばいいんだよ
可搬性の幻想に囚われると逆に生産性が落ちる >>570
そんなの何やりたいのかで答えは変わってくるだろ
漠然とした質問には漠然とした回答しか返ってこないぞ >>575
パソコンの大先生にありがち。知識は少しはあると自負のアンバランスからだな awk で丸飲みしちゃえ
1ファイル1配列
メモリ節約なら
1行ずつ読むのをシンクロさせる >>575
ほんとそれなw
できるのに、知識ないやつほどぐだぐだとレスをする
答えられないのを質問者のせいにする
exec 3<file1.txt
exec 4<file2.txt
read -r file1<&3
read -r file2<&4
echo "$file1 $file2"
read -r file1<&3
read -r file2<&4
echo "$file1 $file2" ちなみに>>580は
一回目のechoはファイルの1行目、
二回目のechoはファイルの2行目が
ちゃんと表示されるからなw
お前ら勉強してちゃんと質問に答えられるようになれよ
中途半端な知識で満足するな >>581
覚えたてで見てほしくてしようがないんだよ
生暖かい目で見守ろうやw などと、質問には答えずに
それでも悔しいからか、レスだけはするようで すげえ嫌な感じの方法思い付いた。
まず二つのファイルの行数だけ wc -l で調べ、小さい方を max に入れておく。
n=1 にしてから max までループさせて、ループの中で awk を使って NR==$n の一行を双方のファイルから抜き出してそれぞれ別の変数に入れる。
なんてことをすると2つの(またはそれよりも多くの)ファイルから1行抜き出して何かをする事は可能だ。
しかし行が長くなればなるほど無駄な処理が増えて時間が掛かることは言うまでもない。
大変効率の悪い方法だ。 >>582
それやりたいなら普通はpaste使うけどな >>585
その効率の悪い方法を実装するとして、wcもawkもいらんのでは?
行数を数えるのも、特定の行を読み込むのもシェルスクリプトだけでできるし。
>>580のやり方、同時に2つのファイルを開いて処理する方法で
実現できないような場合には使えるかも。ファイルのサイズが小さいなら問題にならないし >>586
あ、そうだね。
区切り文字とうするかだけの問題か。 >>586
> それやりたいなら普通はpaste使うけどな
残念ながらpasteでは自由な処理ができない
例えば、1つ目のファイルに書いてある命令を解釈しながら
2つ目のファイルを読み込んだり、他の処理をしたりとかね。 で、POSIXで簡単にできることを、答えられずに
他の言語でやれとか、自由な処理をしたいっていうのに
それを理解しない答えを返してる奴ら
質問者の俺自身に、完璧な答えを出された気持ちはどう?w またいい問題を思いついたら、質問(?)してやるから
じゃーねーw >>590
だからやりたいことを先に言えよ
お前はシェルスクリプトの前に質問の仕方から勉強しろ >>593
同時に二つのファイルを開いて処理したい
って言った。
処理の内容は自由に変えられる
って言った。
同時に二つのファイルを開く以外のなにも条件として出してない
それができれば、いろいろと応用が効く
特定のことしかできないdiffやpasteでは
処理の内容が変えられないだろ うーん、、、こんな感じ?
$ paste -d '\n' file1 file2 | xargs -d '\n' -n 2 | sh
file1 と file2 の内容例
file1:
====
ls
cp
mv
====
file2:
====
.
x y
y z
==== あー。「どうだ俺はこんなにできるんだすごいだろう」みたいな。
じゃあ本当にやりたかった事は複数ファイル処理ではなくて自分の能力自慢か。
人から認められて承認欲求を満たしたいってことでもあるかな。
いつも人からバカにされてるから何かで人をバカにしたいというのもあるかも知れない。
合掌。 >>598
後出し要件からするとそんな感じ
また要件変わると思うw >>596
> なんで自分でわかるのに質問したのか謎
質問した時点では知らなかったよ?w >>598
後出しじゃない用件を言うと、
処理したい内容を自由に変えられないといけない
要件は同時に二つのファイルを開いて
いろんな処理をしたいってことだけ
ま、もう答えは出したがw >>599
最初に用件をちゃんといってるのに、例をいうとその例しかできない方法を出すし
その質問にたいする曲解を潰していくうちに、その時間で自分で調べて解決できてしまうんだから
どうしろっていうんだw やっぱ「自決しました」で終わらせたほうが良かったか? >>603
普通にわからなくて質問していてやがて自分でわかった場合、普通はそれまでに答えてくれた人に対するお礼をするしこういう方法で出来ましたと自分のやったことを書く。
君の場合なぜか答えてくれた人に対する感謝の念がない。書かれたことが間違いや見当外れのことであっても普通は書いてくれたというだけで感謝するものだ。
しないとするなら少なくともその質問は質問に偽装された何か別のものだ。 >>604
teratailとかSOで叩かれてこい >>605
いい加減、客様は神様です。はやめたほうが良いよw >>607
言っている意味がわからない。何か特殊な宗教でも信奉しているのかね? >>608
回答者のほうが偉いみたいな考え方。
質問者と回答者は対等です。 >>609
対等じゃないよ。金を出す側と受け取る側と同じだもの。同じわけがないじゃん。
君はなんでそんな現実と食い違う思想を持ってるんだ?それでは人とのトラブルになるだけで世の中渡っていけんだろう。 >>610
どうやら日本の礼儀が理解できないようだ
今問題になっている隣国の人間なんだろう 日本の礼儀と隣国の話しかできないのが世界が狭いよな >>611
何かを与えてくれたらお礼をするのは国に関係なくどこでも共通の礼儀だが、君はそれをしないばかりか与えてもらって当然と考えるとするならば、それは正に今の韓国と同じだね。 優遇して与えていた側に礼を言わないばかりか盗人猛々しいとでも言うかね? ということで、質問に対して
答えを返した俺に感謝しろ
という話さ 俺は別に自決しましたで終わらせても良かったんだが、
俺ができるってことを示さなければ、
シェルスクリプトで同時に二つのファイルを開けるってことも
知らなかったんだろうな この先の人生、似たような問題に直面したとき、
今日の会話を思い出しながらも、なかったことにして
俺が回答したテクニックを使うのだろう >>615
質問者は君自信だ。それに関しては君が君に感謝すれば良い。他の人は少なくとも同じ質問はしていないのだから君に感謝する必要はない。
という、普通の事が君にはわからないのか?発達障害か何かか?だったらしょうがないから形だけ他の人を真似て合わせろ。そうすれば無用なトラブルは減らせる。 ん?他の人って会話に参加してる人だけのことだと思ってるのか?
検索で見つけた人とかあるだろう。
相変わらず視野が狭いんだな。 検索した人は俺に感謝する。ここでレスしてたやつも同じ問題がでたとき
嫌々ながら俺に感謝する。ウィン♪ウィン♪ってやつではないか どうでもいいけどアレを「完璧な回答」とか言ってる時点でお察しw
ファイルディスクリプタを使った方法にはPOSIXの範囲では解決できない重大な落とし穴がある。
まあ態々言わなくても分かるだろうから,明言はしないがw ああ一応分からん人の為にヒントをいうと,実は2018年あたりの過去スレで言及してる。 ※その落とし穴がなんなのか言わないのは、わからん人のためよりも
俺に意地悪をすることを選んだから。結局それがそいつの本性なんだよ。 {{"item1":["key1":"value1"]},{"item2":["key2":"value2"]}}
{{"item1":["key1":"value1"]}}
{}
{{"item1":["key1":"value1"]},{"item2":["key2":"value2"]},{"item3":["key3":"value3"]}}
みたいに中途半端なjsonがたくさん混ざっているファイルを
item1,item2,item3
value1,value2,
value1,,
,,
value1,value2,value3
のような綺麗なcsvで出力する方法ってありますか?
jqコマンドを使っても上手くいかず…… >>629
それ中途半端なjsonじゃねーよ
jsonlという形式だ。jsonエル 1行ずつループで回してもできそうだが、なんどもjqコマンドを呼び出すことになって
時間がかかりそうだから、
[
1行目 ,
2行目 ,
3行目 ,
4行目
]
みたいに変換して、jq一発にしたほうが速いだろうな。
そのやり方は、俺以外でも答えられるやろ? >>629
GNU awk 4.0.0 以降で
$ gawk -ijoin -vFPAT='"[^"]+"' '{
for(i=1;i<=NF;i+=3){
item[$i]=1
row[NR,$i]=$(i+2)
}
}END{
for(i in item){x[n++]=i}
n--
print join(x,0,n,",")
for(i=1;i<=NR;i++){
k=0
for(j in x){
r[k++]=row[i,x[j]]
}
print join(r,0,n,",")
}
}' data.jsonl これは、Ruby で、JSON.parse できない。
何や、この形式は?
{"item1":["key1":"value1"]}
[ ] の中に、{ } を入れたら、OK だが、
{"item1":[{"key1":"value1"}]} https://jsonformatter.curiousconcept.com/
このサイトで、JSON の形式が正しいかどうかチェックしたら、エラーになった!
{"item1":["key1":"value1"]}
Error:Expecting comma or ], not colon. >>632
すげえ!
口先だけの>>631とは全然違うわw >>629
{{"item1":["key1":"value1"]}}
じゃなくて
{{"aaaa":["bbbb":"cccc"]}}
でも
"cccc" って表示されるけどOK?
あと {{"item1":["key1":"val\"ue1"]}}
みたいに " がデータに入ってる場合はあるの?
それと key1、key2、key3 ってキー名が変わるのは正しいの?
jsonlとしても正しくないけど、書き間違いじゃないの? >>629
これJSONじゃないしフォーマットおかしいってだけじゃね?
正しいJSONならjqだけでcsv変換できるぞ JavaScript で、: は、オブジェクトの属性だろ。
だから、{ } 内でしか使えない
だから、1 はダメで、2, 3 はOK
1. {"item1":["key1":"value1"]}
2.1 {"item1":["value1"]}
2.2 {"item1":["key1","value1"]}
3. {"item1":[{"key1":"value1"}]} フォーマットが不自然なんだよな。独自フォーマットなら
その仕様を言ってくれないと答えようがない。
例えば、そこに書いてあるキー以外も存在するのか?とか
改行はどうなってるのかとか >>629は「中途半端なjson」と言ってるから分かってる気はするけど、
半可通な上司か先輩がJSONを分かったつもりになってるだけで
仕様なんかちゃんと考えて無いと思うなw 本物のjsonにしちゃえ
独自フォーマットする利点ないでしょ 独自形式など、作るだけ無駄
パーサーを作るにも、特殊文字のエスケープ処理など、バグが増えるだけ! 昨日質問したものですが中途半端に書いてしまい申し訳ありませんでした
まだ勉強不足の学生でして……
こっちが正しいjsonと出力させたい内容です
{"aaa":{"bbb":["ccc"]},"xxx":{"yyy":["zzz"]},"あああ":{"いいい":["ううう"]}}
{"aaa":{"bbb":["ccc"]},"xxx":{"yyy":["zzz"]}}
{}
{"aaa":{"bbb":["ccc"]}}
↓
aaa,xxx,あああ
ccc,zzz,いいい
ccc,zzz,
,,
ccc,, aaa,xxx,あああ
ccc,zzz,ううう
ccc,zzz,
,,
ccc,,
です 連レスすみません
例えばaaaとあああだけ抜き取りたい場合
さきほどのjsonlから
aaa,あああ
ccc,ううう
ccc,
,
ccc,
と表示させる方法も知りたいです。
全部表示させた後にawkで削除した方がいいのでしょうか? >>643
学生なら先生に聞けばいいじゃん。
宿題?それでも先生に聞いていいんだよ。
まあ、ここでは丁度良いお題にもなるから良いかも知れないが、宿題の提出期限とかそちらの都合は無視されるよ。 >>646
$ ... | cut -d, -f1,3 >>646
もとのデータが悪かっただけ。
jsonlだったらjqで普通に扱える。
echo "aaa,xxx,あああ";
jq -r '[.aaa.bbb[0], .xxx.yyy[0], ."あああ"."いいい"[0]] | @csv' data.jsonl
ダブルクォートがいらないなら、@csvをjoin(",")にする
こことか見れば良い
https://medium.com/veltra-engineering/jq-supports-json-to-csv-fb5c951a9575 >>650
おおおおお!!!ありがとうございます!!!
自分がやったときは完全一致してないとエラーが起きてましたのでありがたいです
今後はROMってもっと勉強します なるほどjqコマンドだけでやるにはこうすればいいのか
jq -r -s '["aaa","xxx","あああ"], (.[] | [.aaa.bbb[0], .xxx.yyy[0], ."あああ"."いいい"[0]]) | @csv' data.jsonl 今調べてみたら
.aaa.bbb[]と入力していたので全部一致してないとエラーになってたっぽいです
.aaa.bbb[0]に変えている>>650では一致してないところも空欄で出力されてましたので求めるものでした >>653
もしかして皮肉という概念をご存知ない…? >>655
それ配列ってことは要素数が1以上の場合もあるわけだよね
先頭だけでいいの? >>658
問題ないならいいけど [0] より []? 使ったほうが良いよ bashって可変長引数で綺麗に処理できないの?
bash test.sh a b c d e
って打ったら
xaz,xbz,xcz,xdz,xez
bash test.sh a b c
って打ったら
xaz,xbz,xcz
って出るものを作りたいんだが$@を使って色々やっても
xa b c d ez,
って出力しかできぬ >>660
あんたが可変長引数を綺麗に勝利できないだけ
printf '%s,' a b c
a,b,c, printf 'x%sz,' a b c d e
xaz,xbz,xcz,xdz,xez, >>660
while [ $# -gt 0 ];
do
printf x
printf $1
printf "z\n"
shift
done
sh multi_arg.sh a b c d e
xaz
xbz
xcz
xdz
xez
\nいらなかったな
あと間に,でやるやつ必要か
そのへんpass ぶっちゃけ $@ を使ってどうやれば
xa b c d ez, が出せるんだろうって悩むレベルw $ set -- {a..e}
$ l=;for v in "$@";do l="${l}${l:+,}${v}";done;echo "$l"
for 文で "in" を省略すると "$@" が対象になるので
$ l=;for v;do l="${l}${l:+,}${v}";done;echo "$l"
としても可。 いけね、x と z で挟むの忘れてたわ
$ l=;for v;do l="${l}${l:+,}x${v}z";done;echo "$l" >>660や
これを1まとめの変数にする方法ってあるか?
bash test.sh a b c d
って打つと↓を変数で使えるようにしたい(最後だけ,を外して)
xaz,xbz,xcz,xdz
ループさせて配列に入れて${test[@]}でxaz,xbz,xcz,xdz,
って出力させることならできたけど最後の,が邪魔で仕方ない > これを1まとめの変数にする方法ってあるか?
あるに決まってるだろ。
自分でやり方を模索しろや
> 最後の,が邪魔で仕方ない
ならつかないようにするか消せばいいだけだろ シェルスクリプト特有のテクニックがわからないならともかく
常識的なやり方すら見いだせないなら適性無いで マウント上等!教えてくれ!
${test[@]%,*}でいけると思ったが、これって配列じゃ無理なんか
悔しいねぇw >>668
こいつ昨日の>>626か?
知識があるのは結構だが偏屈な理由でそれを教えようとしないのは目障りだからやめろ。
公共の場所だ,ちっとは考えて行動しろ。
もしも教えたくないのなら,最初から反応するな。 おいおい。IDみろよ。俺は重大な落とし穴があるで
教えんけどなー。みたいなことは言わない。 >>667
$ cat ./test.sh
eval -- "var=$(printf 'x%sz,' $@ | sed -e 's/,$//')"
echo $var
$ bash ./test.sh a b c d
xaz,xbz,xcz,xdz
どうぞ。 シェルスクリプトにこだわっても意味内
単なる自己満足 >>674
evalいらねーだろ。その程度でいーばるーなよw あと、eval の -- は POSIX準拠じゃない。 dashではエラーになるな。 それと $@(と$var)にダブルクォートがついてないのもマイナス点だな >>674
$ bash ./test.sh a "b c" d
xaz,xbz,xcz,xdz
となってしまうので、
var=$(printf 'x%sz,' "$@" | sed -e 's/,$//')
か
var=$(printf 'x%sz,' "$@" | head -c -1) 多分配列つめこんで paste で糊付けしてくれる
paste はいわゆる join()のはず sed呼び出すぐらいならParameter expansionを使ったほうが楽で速いだろう お前らありがとう
want="$(IFS=,; echo "${test[*]}"}"
ってやったら求めるものが出せた >>677
bash前提のスクリプトなんですがそれは カッコの対応がおかしい。
サブシェルに入れる理由がないわけじゃないが、これで処理終了なら遅くなるだけ
この程度でbash依存するのは無駄。長くなってるだけ >>683
じゃあbash 2.05aとそれ以前でエラーになると言っておこう ${l}${l:+,} は俺もよく使うが、ループで毎回比較処理をすることになるし、
最後に末尾処理をしたほうが、速いんじゃないかなーって
常々思ってしまう。lが二回出てくるから1行が長くなることが多いし 試してみたけどやっぱりだ。最後に末尾処理するほうが速い。
dashやkshだと2倍ぐらい差が出る。
bashやzshはこういう処理が何故か遅くて差もあまり出ないけど Ruby では、Array#join で自動的に、最後の区切り文字を削除してくれる
ary = [ "a", "b" ]
p ary.join( "," )
#=> "a,b" そりゃそうだ joinは配列から文字列に変換するときに
間の糊付けをしてくれるのだから 単純な join でセパレータが一文字なら定番の
$ (IFS=,; echo "$*")
で良いのだろうけど >>688
1行でできるから:+を使いたくなるけどね。
でも変数名が長いと見づらくなっちゃう。
余計なものをくっつけて、最後に削るのは一見無駄なことをしてるように思えるけど
そっちの方が速いってはっきりしたので、これからは気兼ねなく、
:+を使わない方法を使えるようになったよ
>>691
コマンド置換だと遅くなるよ。
IFS=,; echo "$*" でいいでしょ? IFSを戻したいなら戻せばいいだけだし。
それに変数に入れる場合、var="$*" だと最後の改行もちゃんと保存されるけど
コマンド置換を使うと消えてしまう。 >>691で
> 単純な join でセパレータが一文字なら
という話が出たので、問題。
今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが
それでもIFS=,を使うならばどうすればよいだろうか?
言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、
さてどうすればよいだろうか? そんな面倒なことをシェルスクリプトでやるのはやめる
客が7&いじゃなければ大丈夫だろ >>667
$ var=$(printf "x${1}z";shift;(($#)) && printf ',%sz' "${@/#/x}") >>694
$ (set -- "${@/#/x}";set -- "${@/%/z}";IFS=,;echo "$*") >>697
とっても無理矢理感があるなw
まず引き数がないときに、xzと表示されるバグが有る。
あと後半意味がわからんw
単純に && printf ',x%sz' "$@" でいいんでないの?
(($#))もいらんし >>698
なるほど。bash依存だとそれができるのか。それは盲点だった。
書いてなかったけど、POSIX準拠の場合はどうなるだろうか? >>699
shift 後の $# が 0 以上だと成功になってしまうので引数が1個の場合、
$ set -- a
$ var=$(printf "x${1}z";shift&&printf ',%sz' "${@/#/x}")
$ echo "$var"
xaz,z
となってしまう。
一応、引数は1個以上を想定して、2個以上なら (($#))&& は不要なんだけどね
引数なしでも処理するなら、もっと酷くなるw
var=$((($#))&&{ printf "x${1}z";shift;(($#))&&printf ',%sz' "${@/#/x}"; }) おっと、
var=$((($#))&&{ printf "x${1}z";shift;(($#))&&printf ',x%sz' "$@"; })
だね ああprintfは引き数がない場合でも表示されるのか >>673
仮に別人だとしても同じようなことしてるぞ。
自分で模索しろとか言って解法を提示していないにもかかわらず
ある程度要求を満たす解法が上がった瞬間それにケチ付けはじめてるじゃん。
もしもほんとうに「自分で模索しろ」って思ってんなら黙っときゃいい話。
わざわざ人が答えを述べてからそれに乗っかるなんてマネする必要ない。 >>700
このコマンドラインをPOSIXに準じたものにするには
(愚直に言えば)単に${VAR/aaa/bbb}をprintf '%s' "$VAR" | sed -e 's/aaa/bbb/'
に変えればいいだけでは?
それかPOSIXの範疇で変数の置換展開を実現する方法を訊いているのか?
それじゃあ多分無理だ。 まあ尤もprintf sedなんていちいち呼び出すなんてバカなマネは普通しないが。 >>705
違うでー、引き数の a b c を xaz xbz xcz にする方法を
聞いてるんだぜー このテクニックはいろいろと応用が効くのだ!キリッ! shiftを上手く使えば
N番目以降の引数だけ別の処理に使うことってできるよね?
あとbashの引数って10超えるとおかしくなるってマジ? >>709
嘘 ${10} を使えばいい。
(相当古いシェルは非対応だったりするらしいが) 引数をうまく扱うにはshift、
引数を高度に扱うにはevalを使う >>707
じゃあこれでどう?
態々IFS弄ったり何度も置換したりする必要はない。
printf 'x%sz ' "$@" | sed -e 's/ $/\
/' awkとか使ってtsvを別のtsvに挿入させる方法ってある?
hoge.tsv
a b e
1 2 5
huga.tsv
c d
3 4
↓
hoge_huga.tsv
a b c d e
1 2 3 4 5
みたいな 行と列をひっくり返す transpose っていう awk script を作って、
========
#!/usr/bin/awk -f
{for(i=1;i<=NF;i++) a[NR,i]=$i}
END{
for(j=1;j<=NF;j++) {
str=a[1,j]
for(i=2;i<=NR;i++) str=str" "a[i,j]
print str
}
}
========
$ paste hoge.tsv huga.tsv | ./transpose | sort -k1,1 | ./transpose
a b c d e
1 2 3 4 5 >>714
paste hoge.tsv huga.tsv | awk 'BEGIN{OFS="\t"}{print $1,$2,$4,$5,$3}'
a b c d e
1 2 3 4 5 >>715
こっちのやりかたのほうが汎用的だし個人的には好きかな。 (´-`).。oO(列の挿入なのに何故ソートするんだろう) む。出遅れたか。気づいていたんだが書き込む時間がなかった。
>>716 と近いが、tsvなら入力をタブ文字にしたほうが良いだろう
でないとスペースまで区切りとして扱われる
paste hoge.tsv huga.tsv | awk -F"\t" -v OFS="\t" '{print $1,$2,$4,$5,$3}' >>718
それな。いかにも要求されてないことをやってるだろw
このスレ、例を出すと、その例を"だけ"に通用するコード書くやつ多いぞ
それを訂正するのに労力がかかるって言った意味わかるやろ? >>713
その答えもありだが、それはそれとして
引き数の a b c を xaz xbz xcz にするPOSIX準拠のテクニックって
あまり知られてないのか?
まさかこんなに出ないとは思わなかった。 同時に二つのファイルを開くやり方も分かったことだし、
ついでにシェルスクリプトだけで実現するやり方を書いておこう
#!/bin/sh
exec 3<./hoge.tsv
exec 4<./huga.tsv
IFS=$(printf '\t')
until
eof=1
read -r col1 col2 col3 <&3 && eof=''
read -r col4 col5 <&4 && eof=''
[ "$eof" ]
do
set -- "$col1" "$col2" "$col4" "$col5" "$col3"
echo "$*"
done >>720
おおおおおおありがてぇ!
区切りもタブ指定しないとyyyy-mm-dd hh-mm-ssとかがずれるよね GNU datamashってのがあんだね。
$ paste hoge.tsv huga.tsv | datamash transpose | sort | datamash transpose
とか。挿入じゃなくてソートだけど。 ソートしたのは >>714 で hoge.tsv と huga.tsv の一行目の項目が辞書順に
並ぶ様に挿入する、って思ったんだよね >>720
FSのデフォルトはスペースとタブだから指定する必要ないよ なんかこのスレに書き込む質問者ってお客は神様だみたいな発想してる人多い印象がある。
多少の問題は自力で解決しろよって思うわ。
「その例"だけ"に〜」とか喚いてるけど,その「例」とやらがマズい例なのでは?とは1ミリも考えてなさそう。
いつも自分が正しい。問題の責任は他人にある。
まあスレの全員がそうじゃないけどね。極一部。 >>728
アホか、スペースとタブだからタブだけにするんやろw >>729
例っつーのはな、本題があって、それを補足するためのものなんだよ。
本題が本当にやりたいこと、
お前>>714本題の文章「awkとか使ってtsvを別のtsvに挿入させる方法ってある?」
読んで、ソートしたいって思うか?
お前は「いつも自分の解答が正しい。問題の責任は質問した他人にある。」
と考えてるんやろ? (´-`).。oO(勘違いしたって言ってるんだからもうええやん) >>694の問題は本日24:00で締め切るでー
シェルスクリプトに詳しいと思ってる人、
挑戦してみてやー >>733
スレ更新してから書き込むまでに、34秒以上かかっただけだよw しゅ‐き【主気】
?名? そのものがいつも持っている運気。⇔客気(かっき)。〔夢渓筆談‐象数・一〕 はい、24:00締め切りでーす。
> 引き数 a b c を xaz xbz xcz にすればいいわけだが、
> さてどうすればよいだろうか?
解答
for i in "$@"; do
set -- "$@" "x${i}z"
shift
done 別解
for i in "$@"; do
set -- "$@" "x${i}z"
done
shift $(($# / 2)) なんか対抗するつもりはないけど俺の回答のほうが何やってるか分かりやすい気がする…。
まあトリッキーなシェルスクリプトを書くのは個人の自由だけど >>742
こんなのトリッキーのうちに入らんでしょ。
シャルスクリプト特有の書き方ってだけ
POSIXの範囲ではシェルスクリプトで使える配列は
パラメータ引数しか無い。その貴重な配列を使いこなせば
bash依存もせずにすむよ bashでいいじゃん
bash動かないようなクソ環境なんかないだろ今時 POSIX原理主義者の彼にはそんな煽りは通用しない! そのとおり。Debianがdashを使ってるのだ。どうしようもない。 >>743
うむ。トリッキーと書いたのは失敗だったな。
ちょっと勘違いを生んでしまった。
繰り返すけどあなたの解答を否定する気は全くないし,自分の解答が一番だなんて思ってないけど
引数「a b c d」を「xaz xbz xcz」に変換するにあたって
「手続き型言語としてのシェルスクリプト」を考えたときに
「引数に順次同じ変換を施して→余計なものを置換する」ほうが
「引数の仕様を利用してfor文を回す→(置き換えられた)引数として利用」
よりも単純かなぁと思っただけ。
あと(問題文に書いてないので推測するしかないが)引数自体はそのまま残したい場合もあるだろうから
引数を置き換えてしまう方法だと不本意な結果を招くかもしれないとも思った。
それこそ「引数を置き換えて新たな引数として利用したい」という要求ならばfor文とsetコマンドを使った方法が
いいんだろうけども。
ところで>>713がBash依存という話だけど
sed -e 's/ $/\
'
↑これってBashでしか使えなかったっけ? sedで何かから改行に置換する方法。
一応The Open Groupの仕様書には
A line can be split by substituting a <newline> into it.
The application shall escape the <newline> in the replacement by preceding it by a <backslash>.
と書かれてるんだけど。 bash依存っていうのは ${test[@]} とか printf ',%sz' "${@/#/x}" のことな >>713に関して言えば、
引き数の a b c を xaz xbz xcz にする方法を聞いてるのに
質問の答になってないねとしか言えないから >>750
うん?
$ cat ./test.sh
#!/bin/sh
printf 'x%sz ' "$@" | sed -e 's/ $/\
/'
$ ./test.sh a b c
xaz xbz xcz
となって要求を満してそうなんだけども,違うのかな? >>694 再掲
> 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが
> それでもIFS=,を使うならばどうすればよいだろうか?
>
> 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、
> さてどうすればよいだろうか?
>>738または>>739でパラメータ引数$@に入ってないと
IFS=,を使って xaz,xbz,xcz にすることができないだろ
問題をちゃんと読んでいれば、わかるはずのことだが $@ の中身が printable character だけなら GNU awk の SUBSEP 変数と同じ
様に IFS に '\034'(File Separator) を指定して
[ $# -eq 0 ] && exit 0
IFS=$(printf '\034');set -- $(printf "x%sz${IFS}" "$@")
IFS=,;echo "$*"
とか 訂正
それだと "a b" のように引数にスペースが入ってるときにうまく動かない set -- a "b c" d
IFS=$(printf '\034');set -- $(printf "x%sz${IFS}" "$@")
IFS=,;echo "$*"
とすると xaz,xb cz,xdz となるのだが、そういう事じゃなくて? >>758
うん。だから見落としてたw
そうだな。あとはサブシェルを使うから遅いのと、
それよりも、zshだと
$ ./test.sh a b c
xaz,xbz,xcz,
最後に,がつく ぽじっくすに拘ったりぜっしゅに拘ったり急がしやっちゃなw >>760
Bashとか持ち出すとbash 2.xとか今現在どこでも使われていないバージョンのことも考えないといけなくなるぞw
Solarisでさえbash 4なのにw 因みに>>738や>>739はset -uしてると引数が存在しない場合に古いシェルで動かない >>759
zsh だと set -- $(printf "x%sz${IFS}" "$@") 後の $# の値が 4 になるのね
POSIX 的には $# == 3 になるのが正しい動作なのかね? >>752
訊きたいんだけど,
引数を完全に置き換えてしまうことについてはどう思ってる?
再掲するけど
> (問題文に書いてないので推測するしかないが)引数自体はそのまま残したい場合もあるだろうから
> 引数を置き換えてしまう方法だと不本意な結果を招くかもしれないとも思った。
引数自体を弄くる方法だとこういうことになるのでは……? >>752
例えば>>738でIFS=,を使った場合ってどういう挙動になるのが理想なの? >>761
> ぽじっくすに拘ったりぜっしゅに拘ったり急がしやっちゃなw
何いってんの? POSIX互換シェルにこだわってるだけだよ。
POSIXもdashもzshもbashもワケてない
POSIX互換シェルという一つのこだわりw >>763
> set -uしてると引数が存在しない場合に古いシェルで動かない
苦笑(知ってるw)
間違ってないが、具体的にどのシェルで動かないか言えるかい? >>764
> POSIX 的には $# == 3 になるのが正しい動作なのかね?
めんどくさくて調べてないな。
でもzshだけではなく、今は使われてないだろう古いシェルや
とあるシェルの古いバージョンでは4で、後のバージョンでは3になってたりするから
おそらく $# == 3 が正しいのだろう。
だが、現実として動かないシェルがある
POSIX互換シェルに拘ってるといったが、正確にはPOSIX互換シェルと名乗っている
現実に存在するシェルに拘っているというべきか ZshってPOSIX互換を謳ってたっけ?
少なくとも公式ページ[zsh.org]にはそんな記述は見当らんが…。
もしかしてemulate -R shをPOSIX準拠モードとかだと思ってる…? >>770
いやまって。マジで分からんわw
引数「a b c」を「xaz xbz xcz」にする過程でIFS=,を使う場面なんてあるか?
そして仮にあったとして
>>713と>>738とでその時の挙動に違いがあるとは思えんのだが↓
もしかして
引数「a,b,c」を「xaz xbz xcz」にするとかそういう話か?
for i in IFS=, "$@"; do
set -- "$@" "x${i}z"
shift
done
echo "$@"
こんな風に?w >>762
Solarisは10まで(POSIX互換ではない)Bourne Shellが
デフォルトシェルだってのがいただけない
Extended Supportが2021年までらしい。
まあ俺はPOSIXじゃないからという理由で切り捨てることにしてるが >>694
> 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが →分かる
> それでもIFS=,を使うならばどうすればよいだろうか?→そうだな,どうすればいいんだろう。
> 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、→え?空白区切り?今IFS=,の話だよな??
> さてどうすればよいだろうか? →???? >>772
>>694再掲 読める?
> 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが
> それでもIFS=,を使うならばどうすればよいだろうか? >>774
お前プログラマに向いてないよw
推論能力が圧倒的に不足してる
引数が、xaz xbz xcz の状態なら、IFS使って xaz,xbz,xcz にできるだろw
って言っても理解できないんだろうなw >>771
zshのマニュアルにはPOSIXという文字が50個以上存在する
これでPOSIXを意識してないとか考えられんわw >>778
Zsh is able to emulate POSIX shells, but its default mode is not POSIX compatible
なんて書いてあるから何か変数を設定しないとダメみたいだな
色々弄ってるけど $# が 3 にならんのぅ…ソースコード読むしかないかなw >>780
たぶんその挙動はバグで確定だと思うでw >>768の質問には答えてくれないのかな?
set -uしてると引数が存在しない場合に動かない古いシェルはなにか? >>776
うんだってプログラマじゃねーもんw
寧ろその程度の能力でイキれるお前がプログラマっぽくねぇなw
こっちの類推能力も足りんかもしれんが
そっちの説明能力もかなり欠如してんぞw >>782
すまんがその前に>>765に答えてほしい 別にイキってないが、イキってるように見えるのは
俺じゃなくて、お前の問題でしょう? 普通のことなのにお前にはそう見えてしまう。 >>784
何に答えればいいの?
引数を完全に起きかえたいなら置き換えればいいし
置き換えたくないならば、置き換えなければいいだけじゃん なんで>>765みたいな質問が来るのかを推測したが、
提示したコードはそれで「完成したコード」で
そのコードを修正した「応用」は存在しないとか思ってないか?
違うことをしたいならそれに応じて変えればよかろう? >>782
>>786で一応答えを頂いたので,>>768への回答をば。
https://www.in-ulm.de/~mascheck/various/bourne_args/
ここの
These shells behave the old way and need ${1+"$@"}:
に色々載ってるぜ
俺が知らないシェルもあって勉強になったわ。 >>785
うーむ。自省という言葉を教えてあげたいw
まあある程度シェルスクリプトの能力はありそうだが
それ以外が致命的とお見受けするわ……。
ていうかシェルスクリプトの能力ってそんな高める必要ある?
>>713程度が書ければそれで十分。
より高度な,それこそJSONやXMLみたいな階層構造のある
「1行1データ」とは限らない形式のファイルを読み込みたけりゃ,
CなりPerlなりを使えばよろしい。
もしくはjqやらxmllintやらで適切に処理して
シェルスクリプトに掛ければよろしい。 >>788
それを探してきたかw
じゃあそこに書いてない情報を。
poshは<0.10(8年前)ということになってるが、未だ最新版(9ヶ月前)の0.13.2でも修正されていない
だから「古いシェル」は実は間違い
バグ報告はでてるんだがねぇ
posh: set -u prevents using empty argument list
Date: Wed, 3 May 2017 12:24:01 UTC
Found in version posh/0.12.6
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=861743
posh can not use "$@" together with set -u
Date: Wed, 14 Nov 2018 10:00:01 UTC
Found in version posh/0.13.2
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=913718 >>789
> ていうかシェルスクリプトの能力ってそんな高める必要ある?
俺がやりたいことを実現するのに必須だったから
自然と高くなっただけ >>789
無駄だろう、最初から偉ぶりたいのが目的なんだから
他人と同等になっただけでも負けとかなんとか思ってるのだろう >>790
うーん。
まあそうなのかもしれないが
poshを「無意識に」使ってしまう環境なんてあるのだろうか?
例えば#!/bin/shが/usr/bin/bashにリンクされてる環境であれば,
BashのPOSIX互換モード特有のバグには注意しなくてはいけないし,
/bin/shの実体が/usr/bin/bashになってる環境は多いので,
多くの利用者が「今 自分が使っている/bin/shが実はBashだ」と意識することなく
POSIX shで正しく動く筈のシェルスクリプトを走らせることがあると想定できる。
でもposhが既定で/bin/shにリンクされてたりする環境があるとは思えない…。 >>751
この書き方が分かりやすくて良いと思うんだけど何か問題あるの? >>793
何が言いたいのかわからん。
set -uで動かないシェル(例 posh)があると言い出した(>>763)のはあんただろ?
なんで俺が書いたコードがset -uで動かないと言い出した本人が
set -uで動かないシェルを使う環境なんてあるとは思えないって言ってるんだよw 引数を置換するってだけで何をぐだぐだ言ってるんだかw だから>>751は「引数を置換する」コードになってないだろ? オリジナルの引数を置換するのはプログラマーの本能が止めろと言っているw
普通は置換したもの別の変数に入れて使うよな >>801
そのルールを守りつつ、IFS=,でjoinするというテクニックを使って(必須です。カンマ区切りをするときに使用します)
引数 a b c (例です。引数の内容、個数は変わることがあります)から
xaz,xbz,xcz (例です。引数の前後にxとzをつけてカンマ区切りにするという意味です)
という出力を得るコードを書くところまでやるのが君の仕事。
それができれば一人前だ! 「POSIX準拠で」をつけ忘れたなw
そこまで文脈読めてないやつじゃないだろうが >>804
?
俺はシェルスクリプトではやらないが、
他の言語で引数を置換するのはやめろというのはわかるから
その理屈は間違いじゃないとして、じゃあそれをシェルスクリプトでやるには
どうすればいいだろうか?という新たな出題に変えただけだけど?
いや、できるでしょ?これ。 もちろんトリッキーなコードになるだろうけど
(こういうのこそトリッキーというべきだろう) え?
だから>>751でいいじゃん
何か問題あるのか? >>807
自分でルールを守ってない
> 普通は置換したもの別の変数に入れて使うよな >>808
は?
だから出力を変数に入れて使えばいいんだろ それから >>751 に関しては
引数をIFS=,でjoinするならばどうすればいいだろうか?という
出題のルールを守ってないよねってことで>>694に反してる。 >>809
また書くのが遅れたけど、>>751は>>694のルールを守ってないのでだめなんだよ。
その話は終わったって言ってるでしょw >>809
「置換したものを別の変数に入れて」使わなければだめ
「出力したものを別の変数に入れる」のは自分で作ったルールに違反してるw 「やりたいこと」は>>694に書いてあるとおり
「IFS=,でjoinするために引数を置き換える」がやりたいこと(解答はすでに出してる)
んで、新しい問題の「やりたいこと」は>>802に書いてあるとおり 手段が目的化する典型的な例だな
そんな縛りプレイに付き合う気になれんな
で、後からコード出して
こんなのも分からんのか?大したことねえな
ってやりたいんだろ?
それはな、
その問題がつまらないから誰もやらないんだよw >>798
「コードがset -uで動かない」という発言と
「poshを「無意識に」使ってしまう環境なんてあるのだろうか?」という発言は
ほぼ矛盾しないと思うんだけど。
set -uで"$@"が空のとき失敗するシェルはposhだけじゃない。
>>788で示したリンク先を見てくれ。
なぜかあなたはposhに拘ってるけど(最近になっても解決してないからか?)。
poshに限った話じゃないのに,なぜかposhに限定して話を進めてるから困るわ。 あ,ごめん。ID変わってるけど>>797とかです。 >>816
あんたはposhが使われる環境があるとは思えないが
古いシェルが使われる環境はあると思ってset -uの話をしたってこと?
> bash-4.0.0 ... -4.0.27
> dash-0.4.6 ... -0.4.18
> all ksh88
> ksh93 until release t+20090501
> pdksh-5.1.3, -5.2.14
> mksh before R39 (as pdksh descendant)
> posh < 0.10 (as pdksh descendant)
> NetBSD 2 ff. /bin/sh
> all traditional Bourne shells
bash 4.0といえば2009年だね。10年近く前のシェルで動かないからって何?
そんなシェルのことまで考えろって言いたかったの? >>815
俺に出されるのが嫌なら、お前が先に出せばいいやんw >>819
問題がつまらないって言ってるだけだ
なんで俺が問題出さなきゃならんのよ
お題スレでも行けや な?日本語の読解力に問題があるやろ?
俺は>>815にレスをしていて、その>>815は
> で、後からコード出して
と書いてあるように、"出す"のは"コード"という話をしてるのに
"問題"を出す話だと勘違いしてくる。
もうね。日本語のレベルでおかしいから、会話にならんのよ。 >>821
お前の言葉が足りないだけだ
エスパー期待するなよアホ 足りないなら足りない部分を指摘するべき。
自分で勘違いしておいて、後から足りなかったんだっていうなよw >>818
うん。
だって>>685でbash 2.xの話をしてるということは
少なくともBashがそのバージョンであった時代くらいまでは考えるべきなんでしょ? OSXのデフォルトシェルがBash3だったはずと思ったら、最新のOSXだとZshになってるんだな
ま、LTSの古いOSとか、BSD系だとBash4じゃないのも結構あってまだ動いてると思う 実務だとプログラミングって才能とかよりどれだけ知識を蓄えてるかの方が重要だよね?
このスレに居る猛者はどうやって強くなったんすか 才能のないのはまず脱落する。
体力のないのもすぐ脱落する。
あとは下積みあるのみ。 シェルスクリプトの才能ってなに?
驕り高ぶらないこと?w
↑半分本気 シェルスクリプトって5行以内で使うルールで使ってるけど
引数をたくさん使いたいっていう有用なケースってある? >>829
その時代まで考えることと、poshが最新版でも
直ってないことは矛盾しないんだがw >>830
>>2にも書いてあるが、/bin/shの実体が何かわからん時代になったからな
> FreeBSD ユーザーは /bin/sh の実体が ash なので注意。
> Solaris, OpenBSD ユーザーは /bin/sh の実体が ksh なので注意。
> macOS 10.15以降のユーザーは/bin/sh の実体が zsh なので注意。
> android ユーザーは /bin/sh の実体が mksh なので注意。
bashで動けば良いんでしょ?という時代は終わった。
POSIX準拠で書かないと多くの環境で動かない。 >>834
複数ファイルに対して同一の処理をする時。
例えば特定の文字コードに変換するとか。 クロスプラットフォーム必要なケースで、シェルスクリプトで作り込んだりしないよ
PerlかPythonか、Windowsも対応するならGoとか使う >>838
逆じゃね? 何かをシェルスクリプトで作ったとして
多くの環境で使うなら、多くの環境で動かんとだめでしょw >>841
例えば組み込み機器でPerlやPythonも入ってない、入れられないときはどうする?
シェルスクリプトはかろうじて使える(最初から入ってるから)
Goはバイナリがでかいから、空き容量も制限されてる組み込み機器には入れたくない
今はIoT時代ですよ(笑) >>843
シェルスクリプトってすごいんだな
そんな組み込みでも走るとは >>844
組み込みLinux用に作られたBusyBoxっていうのがあって、
一つのバイナリに様々な外部コマンド(catとかsedとかwcとか)が詰め込まれてる。
そのBusyboxにashも組み込まれてる。
ただし様々な外部コマンドが組み込まれてるといっても、POSIX完全準拠を
目指しているわけじゃなくて、容量節約のためあまり使われないオプションを実装していない。
それでもシェル(ash)はPOSIX準拠になってる。
BSDなどでもそうなんだが外部コマンドはオプションが違うことがある。
オプションの違いでLinuxで動いたものがMacで動かなかったりするが
シェルスクリプトで実装していればそういうこともない。 (Busyboxは組み込み用ではあるが、組み込みLinux用とは限らんかw) (´-`).。oO(IoT機器で文字列くっつけたりTSVファイルを混ぜたりしているのか… そりゃすることもあるだろw
IoTはモノのインターネットの略なんだから
インターネットにあるものと連携してるよ。
TSVやCSVだけじゃなくJSONやXMLやYAMLも扱いたい
(簡易なことならsedなどで対応できるが) やっぱりどこでも動くシェルスクリプトなんて幻想なんだね… (´-`).。oO(心の声に反応しないで欲しい…w >>849
POSIX準拠でシェルスクリプトで書けば可能だって言ってんだろw 今現在でも世界中で書かれているシェルスクリプトの一体何%がPOSIX準拠なのか。
ま、実質幻想だね。 (´-`).。oO(心は常に幻想を追い求める…原理主義者の業の深さよ… 具体性ゼロだな。単なる可能性想像上だけの話だな
多くは限られた環境しか使わんし、それで動けばいい、何か他で使うようなときに問題があったら考えようで十分だろな
使ってる環境(OS)にデフォで入っている汎用スクリプトもそのOSでしか動きませんというのもそんなもんだし 例えば、gitはいろんな環境で使うが、35.7%がシェルスクリプトである
https://github.com/git/git (´-`).。oO(いつからgitはPOSIXコマンドになったんだろう) 35.7%っていってるんだから、探すまでもなく他の使ってるってわかるだろw >>857
gitがPOSIXコマンドだって誰も言ってない 少なくとも git-filter-branch.sh は perl がインストールされていない環境では
動作しない…それに、シェルスクリプトの表現能力が(他の言語に比べて相
対的に)低いために全体の占める割合が高くなってしまっているという可能性
も否定できない。別段それが悪いわけではないが。 gitコマンドの話(しかも実装の話)を延々とされても困るわ shbang が全部 #!/usr/bin/env bash だな。個人的にはこの方がいいけどw (´-`).。oO(gitを使うシェルスクリプトはPOSIX準拠じゃないだろ) まさかと思ったが具体性のために git を出したのか。誰がそんなことを聞いているねん
ここにいるどんだけの人がそういう多くの人が使うのを書いているねん。今までのでもほとんど「私用」だろに gitを呼び出すシェルスクリプトの話は誰もしてない >>869
世界の話をするな。ここにいる人たちだけの話をしろ
俺たちの村の話だ。って言いたいわけ? 私用で限られた環境で動けばいいのならPOSIXにこだわる必要性はほぼゼロだな
そしてこのスレでの限られた人を除いては、あくまでも私用範囲といういたって普通の話だろう
だから、あなたがgitレベルの何を書いているのかね?そういう具体性。自分でそういうの書いていないのに? >>865
結局彼は何を言いたいのかな?わけわからんなw ワシもわけわからんw 具体例なら例の某POSIX原理主義者が書いた
ピュアシェルスクリプトの nkf 互換コマンドを出せばいいのに、って思う それが nkf を置き換えるぐらいメジャーだったら出してたのかも
所詮お遊び趣味可能性を示しただけという認識なのかも
よく知らんけどそのスクリプトがどれだけ使われているのか 例えばさ、リモートでHW情報(CPU,メモリ,ディスク...)を取得したいとするじゃん
プラットフォームも様々Linux, FreeBSD, mac...
これPOSIX準拠で書けるかって話
実装はsshでログインしてproc見てってやるじゃん
sshはPOSIXコマンドじゃないし
procはLinuxとBSD系で構成が違うから判断が必要
POSIXで担保できる可搬性には限界があるってことだ >>875
確かに処理速度が遅すぎて全然使い物にならんかったよ…
本人は「遅くてもいいのだ、POSIXシェルがあればどこでも
使えるんだから」って強弁してたけどw どうでもいいけどgitやらrbenvやらって「POSIXシェルスクリプト」で書かれてんの?
そうじゃなきゃ彼の「世界中でPOSIX準拠のシェルスクリプトが動いてる!」って主張は
まったく支援されない,いや寧ろBashに依存したシェルスクリプトがrbenvという世界的な
プログラムで採用されてることによってその説は説得力を失なってるまである。
あ,「俺は『世界中でPOSIX準拠のシェルスクリプトが動いてる』なんて言ってない」なんて
くだらねー反論を先に封じておくと,
>>852に対して>>856を出した訳だから,
当然「シェルスクリプトの一体何%がPOSIX準拠なのか」に答えてる訳だからねぇ。 >>874
> ピュアシェルスクリプトの nkf 互換コマンドを出せばいいのに、って思う
しらんけど、どうせ大部分がawk実装で、
シェルスクリプトで実装してないんだろ? >>879
> どうでもいいけどgitやらrbenvやらって「POSIXシェルスクリプト」で書かれてんの?
話ずれまくりw いろんな環境で動くことが重要って話だろ >>880
いや、POSIXシェルの機能だけを使ってる。可搬性は高いが遅い。 >>883
思いつかない人のために、gitやrbenvという具体例をだしました。 >>882
それがどこにあるのかしらんが、iconvがPOSIXなのでどうでもいいかなw
nkfなんて所詮日本語にしか対応してないし 意味わからん逃げだな
そんなに多くの人が使ってるようなの書いていたら言えるだろうに。具体的に >>886
もしかして俺が誰か特定したかったのか? なにを言っているのか意味わからん
いろんな環境で動くがほぼ絶対なんだろう?そのいろんな環境で動くなにを書いているんだよという素朴な疑問
多くはいろんな環境で動くのを想定してなんていなく、自分の使う環境でしかとしか思わないからな >>888
> そのいろんな環境で動くなにを書いているんだよ
俺の個人的な便利ツール 便利ツールは、俺が興味がある環境すべてで使う。
LinuxやBSDやmacOSや組み込み環境
Unixも興味あるがSorarisとMac以外は個人で使うのが難しいので残念 だったら、いろんな環境で動くがほぼ絶対はあんただけのことだな >>891
俺が和洋中すべての料理を食べるって言ったら、
これらの料理を食べるのは、俺だけってことになるんか? 問.今現在でも世界中で書かれているシェルスクリプトの一体何%がPOSIX準拠なのか
池沼の答え1.gitは35.7%がシェルスクリプトである。俺は問に答えた!
池沼の答え2.rbenvはShellが96.5%。これが具体例だ!
ぼく「・・・」 >>892
また意味わからんことを言い出す
いろんな環境で動くがほぼ絶対と聞いたら俺の個人的な便利ツールってんんだもん、そんなの「あなたの[限られた]環境」の話だろう
結局自分の趣味の話だけじゃないの(なにその>>890のもろ趣味ですは)
それを根拠に他人に押し付ける、他人のを否定するんじゃないよ >>895
お前、他の人が「個人的な便利ツール」を持ってないとでも思ってんのか?
なんで、俺一人から情報もらったら、
世界全部のことを知ったつもりになるのさw >>894
あのー?その問いに答えたつもりはないんですが?
>>855が「具体性ゼロだな。多くは限られた環境しか使わんし、それで動けばいい」っていうから
具体的に、いろんな環境で動かすツールを出したんですが? >>896
意味わからん。なに言っているの?
特定な環境で動く個人的ツールの方が腐るほどあるだろうなんて理解できないの?個人的ツールだろ?意味わかって個人的ツールって使ってるの? >>898
だから、俺の個人ツールの話を聞いただけで、
POSIX準拠が必要なのは、世界中で俺だけだって判断してるのが
意味不明だって言ってるんだがw 根本的に何も理解できないのな
マルチプラットフォームを意識するスクリプトも当然あるし、そうじゃない特定の環境で動けばいいスクリプトも当然ある
あんたは前者ひとつと言うからおかしい。具体的にって聞いたら個人的ツールってことなので、全然いろんな環境で動くがほぼ絶対ではないってことだよ
というか逆に特定の環境で動けばいいの方が多数を占めているのが現実だろう。なぜかは自分で>>890で言っているようなもん
POSIX大好きいろんな環境で動くスクリプト書くのが好きってだけだな >>900
あのさぁ、俺はすべてのシェルスクリプトがPOSIX準拠するべきだなんて一言も言ってないんだが?
お前の思い込みだろ。俺がそう言ってるって。
俺は
POSIX準拠であれば、多くの環境で動く(事実)
俺が使ってる個人ツールは、多くの環境で動かしたい(事実)
俺の個人ツール以外でも、gitに含まれてるスクリプトやrbenvなど多くの環境で動かしたいものはある(事実)
としか言ってないの 他にも俺が言ったことには、
外部コマンドはオプションが異なることがあるので、シェルスクリプトで実装すると、
その違いに振り回されなくてすむ
というのがあります。 >>830に対して>>837なんて言い出す、それも自分ではPOSIXでの人だからそうとられても仕方がないと思うけど
(>>830はbashとzshの違いだし、デフォルトシェルが変わるだけでbashにすればだけで済む話でもあって)
まあ、言う通りなら俺の読み違いってことだな、まあ、すまんかった...腑に落ちないがw POSIXで書く書かないは好きにしろってことなら、すまんかった だいたいPOSIXに従ってないシェルもあるんだから
POSIXで書いたからといってどこでも動くわけじゃないし。
なんというか,ベンダ依存を嫌うあまりPOSIXに「依存」してしまってる感がある。 ここってPOSIXシェル以外の話題もおkなんだよな
なのに、それはbash依存とか外部コマンド使ったら遅いとか押しつけがましいやつがウザいんだよ
そんなもん好きに書かせろやって感じだわ > 最新のOSXだとZshになってるんだな
という話に続いて、他のOSではいろんなシェルが使われてるという話をすることに
なんの問題があるのかわからんが?
bashをインストールするのが大変な環境もあるんだし
POSIX準拠の範囲でできるなら、POSIX準拠でやればいいだろ。対して手間もかからんし。
逆にオプションの違いで動かんことに対応する方が手間なんだよ。
上の方でも出てたけど、sort -Vで動くウェーイってやってたらmacOSで動かんのだろ?
(ぐぐって確かに動かんというような記事ばかりだが、最新のmacOSだと対応してる気もするw) 結局POSIXで書けって言ってるだろうに。ふらふらしてんなあ >>904
> だいたいPOSIXに従ってないシェルもあるんだから
> POSIXで書いたからといってどこでも動くわけじゃないし。
もっといい案があれば採用するが?
条件後出しするなって言われそうだから条件
組み込み機器など含めてソフトウェアを追加するのが困難なシステムでも動く
コンパイルはもとより、クロスコンパイル環境も不要
この条件でできるだけ多くの環境で同じように動く >>908
どこをどう読めば、お前は命令されてるように感じるんだ?w >POSIX準拠の範囲でできるなら、POSIX準拠でやればいいだろ。対して手間もかからんし。
誰に向けて書いているの? 補足
> この条件でできるだけ多くの環境で同じように動く
これは多くの"種類"の環境っていみな
世の中Windowsばかりだろという反論は筋違い >>911
する必要もないのに、bashに依存してる人 それがだろうが。自分で何を書いているのかわかららないの? 別にbashに依存してもいいだろう?それでそのスクリプトの実行に問題がなければ
>俺はすべてのシェルスクリプトがPOSIX準拠するべきだなんて一言も言ってない
と相入れないね 唐揚げにレモンをかけると美味しくなりますよって言ったら、
「俺にレモンをかけろと命令したな!ムキー」って怒るような
話が通じない人が多いw わからんけど、複数が「?」と思ってるのだよ。よく考えような >>919
bashに依存してもいいだろ。というと
POSIXのすることのメリットは矛盾しないからねw
「bashに依存してもいいだろ」はお前の主観で、
POSIX準拠で作ることのメリットは客観的なもの
客観的事実に、主観で反論しないでください >>924
「POSIX好き」は主観
そのPOSIX好きの俺が述べてるPOSIX準拠のメリットは客観 あと11レスで今日一日でこのスレの1/10を俺が占拠したことになる。
お前ら、レス頑張れ! 結局何を言いたいの?POSIXで書け、できるだけそう書けと言いたいの? >>927
POSIX準拠で書けば、メリットがあるので、
POSIX準拠で書く話をしましょう。
ネタがなければ、私が時々問題を出しますよ
興味がない人は見なくていいです。
レスもしなくていいです。 すべてのシェルスクリプトがPOSIX準拠するべきだ
との違いがわからんな ∧∧ ミ _ ドスッ
( ,,)┌─┴┴─┐
/ つ. 終 了 │
〜′ /´ └─┬┬─┘
∪ ∪ ││ _ε3
゛゛'゛'゛ >>929
Javaで書けばいろんなOSで動きます。
と言ったからって、ドライバまでJavaで書けと言ってるんだ!
なんて思いますか? ドライバがJavaで書けるなら書く人もいるだろう。そんなOSがあれば
不適切よくわからん例えだな
結局
すべてのシェルスクリプトがPOSIX準拠するべきだ
と言ってるのね。好きにしろではなくてPOSIXを強く勧める押し付けがましく >>905
少なくとも5年前から
> □A. お約束
> 1. 特記なき場合は #!/bin/sh がデフォルトです。この場合可搬性に注意し、
> Traditional Bourne Shell もしくは、POSIX 相当のスクリプトでお願いします。
> bash / zsh / ksh / ash / dash や OS 等に依存する場合は、明示しましょう。
> 良く分からない方は、使用している OS を書いておけば OK です。是非ご参加下さい。
https://peace.5ch.net/test/read.cgi/unix/1415634843/ >>932
> ドライバがJavaで書けるなら書く人もいるだろう。
そう思うのが普通ですよね?
「書けと命令したんだ!ムキー」ってなる方がおかしい 自分だって否定されたらそうなってるように見えるけど? >>932
Javaで例えれば冷静になって、
> ドライバがJavaで書けるなら書く人もいるだろう。
っていうわけだよね
でも、POSIXで書けばいろんなOSで動きますって言うと、頭に血が上って
> すべてのシェルスクリプトがPOSIX準拠するべきだ
> と言ってるのね。好きにしろではなくてPOSIXを強く勧める押し付けがましく
っていう感想に変わっちゃうんだよねw 俺が「POSIXで書けばいろんな環境で動きます。」って言ったんだから
「POSIXで書けるなら書く人もいるだろう。」って言えばいいだけなのにw
Javaの場合みたいに! 全然わかってなくて、そのレスは酷い。なにか揚げ足とってよろこんでいるように見えるけどw
問題なければいいよどうでもというのと、問題なくてもメリットがあるからこっちに「決まってる」という違い メリットを言うと「こっちに決まってる」という文章が書いてあると
勝手に脳内で補完してるんですか? Javaのメリットを言いました。
メリットがあるから、こっちに「決まってる」と? >POSIX準拠の範囲でできるなら、POSIX準拠でやればいいだろ。対して手間もかからんし
>する必要もないのに、bashに依存してる人
自分で何を言ってきたのか忘れたの? >>941
それだと俺が言ったことを復唱しただけだよw
だからなに? ソコからなんだけど。そんな直前レスに対しての揚げ足とり的なじゃなくw 結局いろいろ逃げてるけど、本心としては
すべてのシェルスクリプトがPOSIX準拠するべきだ
なんだろに。それもただ言ってみただけなのね、なぜか複数が見る掲示板でw
まあいいや >>943
言うべき言葉は何も見つからなかったの?中身がなにもないんだけど? >>944
>>901より
> あのさぁ、俺はすべてのシェルスクリプトがPOSIX準拠するべきだなんて一言も言ってないんだが?
明確に否定してんのに、お前何いってんの? 次のスレタイに【POSIX限定】って付けとけよ
アンチ除けになっていいと思うぞ >>946
とてもそうは見えないという結論だな。俺の結論だから気にしなくていいよw そういや 【POSIX】 sh系互換 シェルスクリプトスレ ってのがあるやん ほんとだ!見逃してた! 次スレの関連リンクに追加しといたよ
【POSIX】 sh系互換 シェルスクリプトスレ
https://mevius.5ch.net/test/read.cgi/tech/1535195112/ ほんとだw
2018/08/25
って、つい先日かと思ったら一年前かw スレ建ててくれたけど、どうかあちらを有効に使っていただきたい ここはPOSIX準拠じゃないスレも対応?
fishとかの話題もどんどん扱うってことかな? fishってPOSIXと互換性はかなり低かったと思うんだが、
最終的に高い互換性を持たせるつもりなん?
https://www.excite.co.jp/news/article/Cobs_1862541/
> POSIX互換シェルとの互換性向上のために&&、||、!をサポート
fishの設計理念5原則(翻訳):使いやすさのための数々の気遣い
http://fish.rubikitch.com/design-document-ja/
> 可能な限り上記の目標を崩すことなく、fishはPOSIXの構文に従うべきです。 最近では PowerShell なんてもあったり
どんどん扱うとかそういうんじゃなくて、そう否定するのはいないんじゃないかな
知らんけど http://fish.rubikitch.com/design-document-ja/
> ・ヒアドキュメントは パイプライン で echo コマンドを使うこととほとんど変わらないので不採用です。
> (訳注:「string trim 複数行文字列リテラル」でも代用可能)
> ・サブシェルとコマンド置換とプロセス置換はとても類似性が強いです。fishは コマンド置換 のみをサポートしています。
> それ以外はブロックまたはpsub標準シェル関数 で実現できます。
> ・別名定義 と シェル関数 の双方を持つことは混乱を招きます。特別にどちらも制限と欠点があるからです。
> fishの関数はいずれの構文の欠点も存在しません。
> ・POSIXのクオートの仕様は馬鹿げています!とくにシングルクォートは!!
やっぱ互換性はないと考えたほうが良いか おい、ついてこいよw
せっかくPOSIX以外の話もしてるんだから >>714-732
Ruby で作った
require "csv"
options = { :headers => true, :col_sep => "\t" }
table_1 = CSV.read( "hoge.tsv", options ) # 読み込み
table_2 = CSV.read( "huga.tsv", options ) # 読み込み
CSV.open( "hoge_huga.tsv", "w", options ) do |csv| # 書き込み
csv << %w(a b c d e) # header
table_1.zip( table_2 ).each do |one, two|
csv << [ one[ "a" ], one[ "b" ], two[ "c" ], two[ "d" ], one[ "e" ] ]
end
end >>970
勘違いしてるぞ。明確に書いてはないかもしれんが a b c d e はヘッダじゃなくてデータだ。
eachは不要。あといつになったら、その古いハッシュの書き方をやめるんだ?
訂正版
require 'csv'
options = { col_sep: "\t" }
table1 = CSV.read('hoge.tsv', options)
table2 = CSV.read('huga.tsv', options)
CSV.open('hoge_huga.tsv', 'w', options) do |csv|
table1.zip(table2) do |one, two|
csv << [one[0], one[1], two[0], two[1], one[2]]
end
end 長いと大変そう
ruby にもこういうのありそう
DB<8> @a = qw(a b e)
DB<9> splice @a, 2, 0, qw(c d)
DB<10> print @a
abcde >>973
それがRubyにはPerlやJavaScriptみたいなspliceがないんだよね
でも今回は、挿入するだけだから、 csv << one.insert(2, *two) が使えるね
順番をもっと柔軟に変えたいってなると面倒だけど >>660
そういやこんなのはいかんの?
てか、こういう答え既に出た?
#!/bin/sh
cf=0
for f
do
if [[ cf -eq 0 ]]; then
cf=1
else
echo -n ','
fi
echo -n "x${f}z"
done
echo '' >>975
echo -n はPOSIX準拠ではない。が、メンテナンスが続いている最新シェルはすべてサポートされている
と思っていたんだが、上の方で出てるboshが対応してなかったわw
やっぱりprintfを使うのが一番なんだろうな 改めて調べ直してみたら、yashも-nに対応してなかった。
echo -n aaa ってやったら、 -n aaa って出力される。
単純な出力以外printfばっかり使ってたから忘れてたw > if [[ cf -eq 0 ]]; then
bash依存する必要がないのに、bash依存してる例 重箱の隅が気になって仕方がないのね
そういうのは原理主義者としか思えないけどw
適切なスレが別にあるとわかったんだからそっちでどうぞ やっぱりどこでも動くシェルスクリプトなんて幻想なんだね bash で書くならシェバンで明示するべし
#!/usr/bin/env bash 間違いはそこだよなあ。単に
#!/bin/bash
と書こうとして、うっかり
#!/bin/sh
にしてしまった感じかな >>979
debianはbash依存をなくすのに苦労したらしいからね。
https://wiki.ubuntu.com/DashAsBinSh
> The major reason to switch the default shell was efficiency.
デフォルトシェルを(dash)に変更する理由は効率性です。
> Programs should be written to the standard,
>and if they use extensions they should declare them;
プログラムは標準で書くべきである。拡張を使うなら宣言しなさい。
正しい言葉だ。
拡張を使う理由がないのに効率性を落とす意味ないからね。 >>980
どこでも動くために、POSIXに準拠することの大切さがわかるよね。 >>982
うっかりじゃなくて、無知だと思うよ。
知ってる人が指摘してあげないとね。 傲慢だな。そうじゃないと今までの自分のレスが馬鹿みたいだから...
知らないのかもしれないが、/bin/sh が bash の場合、ちゃんとは動かない
てか、あっちのスレを行けよ ああ、/bin/sh が bash で、しかも、bash が 3.x の場合かもしれない
/bin/sh が bash であっても、#!/bin/sh だと>>975のスクリプトはうまく動かないのはね。なので、うっかりとしか思えんな > /bin/sh が bash の場合、ちゃんとは動かない
だからちゃんと動かないコードを直すべきでは?
/bin/shはdash, bash, ash, ksh, zsh, mksh のいずれかの可能性がある(他にもあるかもしれない) >>982って言ってるだろ
/bin/sh が bash であっても、#!/bin/sh だと>>975のスクリプトはうまく動かない
ね。詳しく正しくは >>987
全角スペースは見やすくするために流石にわざとだとして、
>>975のスクリプトはbash 2.x以上であれば動くよ。確認済み。
(bash 1系の環境は作ってないのでわからん)
Debian、Ubuntuであれば /bin/sh じゃ動かないので
手元のMacかな?それで試しただけだろうね。 >>989
/bin/shのシンボリックリンクの実体がbash、
つまりposixモードの話をしてるのかもしれないけど、
posixモード(set -o posix)であっても [[ ]] は認識しちゃうからね。
bashのposixモードは、挙動の違いをposixに合わせるだけで
posixにはない拡張機能を無効にすることはないみたい。 なので>>989が何を言いたいのかわからんね。
具体的に、どういう理由でbashで>>975が動かないのか
どのようなエラーが出力されるのかを言えば
説得力も出ると思うよ。
レス待ってるねw #!/bin/sh
てか、sh とコマンド打って起動してでも、echo -n hello は -n hello と表示されるんだなあ。うちのはw
type echo しても echo is a shell builtin だしね。てか、/bin/echo は -n が効くやつだけど ちなみに、bash --posix で起動しても echo -n hello は -n hello にはならん、なぞww > echo -n hello は -n hello と表示されるんだなあ。
POSIXのechoには-nはないからね。-nに依存するコードを書いてはいけない。
POSIX準拠で書く理由が増えたね。 誰かさんも使ってると言っていた環境なんだけどなw
$ which sh
/bin/sh
$ ls -l /bin/sh
-r-xr-xr-x 1 root wheel 618480 5 4 16:05 /bin/sh
$ sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
$ sh
$ echo -n hello
-n hello
$ exit
exit
$ bash --posix
$ echo -n hello
hello$ ま、案外
> /bin/sh が bash であっても、#!/bin/sh だと>>975のスクリプトはうまく動かない
の理由は全角スペースが入ってるからだったりしてねw >>997
よく読めよ。都合が悪くて妄想モードか? このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 40日 19時間 5分 18秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。