シェルスクリプト総合 その32
■ このスレッドは過去ログ倉庫に格納されています
シェルスクリプトに関する総合スレッドです。 全般 ・荒しは無視しましょう。 ・丁寧な姿勢を心掛けましょう。 ・ネチケット(死語)を意識しましょう。 ・「○○(他の言語)でいいやん」は禁止。他のスレに行ってください。 シェルスクリプト総合 その31 https://mevius.5ch.net/test/read.cgi/tech/1565446670/ >>418 CSV形式の一種なのかな。 ただ改行はなくて、常に一行。 あと引用符はあったりなかったりする。 具体的には、m3u8プレイリストの一部を処理したいのよね。 プログラミング言語でやったことあるけど もともとあるデータに手を加えられないなら カンマを違う区切り文字に置き換えたかな 行解析ロジック入れたりもした 最近作ったシェルスクリプトだと 読み込むファイルをちゃんと設計して そんなデータは行末に来るようにした そしてwhile readで処理できるようにしてる 超具体的に言うと(てかここまで直接に状況を晒すとクレクレみたくなるなw) “playlist.m3u8”っていうファイルだとして ↑こういう形式の行が沢山あるんだけど、 ここのRESOLUTIONの値と対応するMOVIE-URIの値をずらずら欲しい。 IFSを変える方法だとやっぱり引用符に関係なく「,」で区切られちゃうのよね while read l; do IFS=','; for s in "$l"; do echo "$s" done done < ./playlist.m3u8 >>423 自分で生成するんだったら区切り文字は絶対に 他の文字と被らないようにするんだけどね…… 面倒になったー index=2,INFO1="abc",INFO2="ab,c" を index=2 INFO1="abc" INFO2="ab c" に変換すれば evalできるよ! あとは頑張ってー >>426 それだと引用符の中のカンマまで変換されちゃうのよね。 まあ、もう簡単に処理する方法はあきらめて AWKやらでガシガシ解析するしかないw んー?戻すとなったらset使ったほうがいいんか? eval set -- index=2 INFO1="abc" INFO2="ab c" $1, $2,・・・代入されるからに処理しやすい > AWKやらでガシガシ解析するしかないw シェルスクリプトでも普通にやればいいんだけどねー 一文字ずつ処理する方法さえ調べれば、 あとは簡単な普通のパーサー こういうのってawkで高度(?)な機能と発想の転換で使ってこなすより 1文字ずつ処理したほうが楽でわかりやすいよな GNU awk なら FPAT が使える echo 'index=2,INFO1="abc",INFO2="ab,c"' | gawk -vFPAT='[^=,"]+=("[^"]*"|[^,]*)' '{print gensub(FPAT, "\\1", "g")}' => 2,"abc","ab,c" >>432 そういうやつね、高度な機能っていうのは 大体動くんだろうけど、仕組みを把握するのがだるいんだよね 仕組みっていうかどこまで動いて、どこが動かないのかの把握 大体動く精神なんだろうけど、それ使う側がそれで 納得できる前提だから、知らない人が使う場合困るんだよな いざ問題が起きたら、対応が逆に大変になる いやぁ、こっちからみると eval や set を使う方がツラいわ… evalやsetは普通にシェルが文法を解釈するのと 同じ動きをするだけなんだからシンプルだろ シェルの構文パーサー自体はしっかりと作られてるんだから でもFPATはだいたい動くという理念で作られてる FPATって単なる正規表現(ERE)でしかないけどな。個人的には正規表現で 考える方が楽でいいし確実。以前に同じ様な事があったけど、 ・変数名にもカンマを使いたい(SQLみたいにバッククォートで括る) ・値の方には複数行のテキストを入れたい(newlineを使える様にして) っていうリクエストがあって大変だったけど、結局 python の CSV パッケージ を使って解決 そもそも正規表現は単語(文字の並び)を見分けるもので その単語の意味(このカンマはどういう意味?)を 見分けるものじゃないんだよ 本来得意ではない意味を区別できるよう拡張していったら 逆にコード見ても何をしているか意味がわからなくなってる コードをパット見てその意味がわからんのは スパゲッティコードと大差ないよ eval 使うのは面白いけど、 $ eval $(echo 'id=$(whoami),hostname=$(hostname),date="$(date)"' | tr , ' ') fork_bomb=$(:(){ :|:& };:) なんて文字列を埋め込まれたら嫌だな… m3u8-file-parser(http://npm.taobao.org/package/m3u8-file-parser )なんてのがあるな playlist のフォーマットって RFC8216 で定義されていたのね >>427 AWKで解析するとして、コンマが引用符の中かそうじゃないかなんて判断できるのかな? 正規表現は>>423 も言ってる通り単に文字の並びを指定するもので ある箇所での文字の「意味」は定義できないからこういう作業には向いてなさそう。 てかお前らいつまで化石みたいな話してんの? PowerShellやれよ お前らが大好きなLinuxにもPowerShell入れられるように成ってるからw もうこれからはハイパーVとかWindowsサーバーとかWSLできないと食ってなるぞお前らまじで Perl ならこんな感じか。 perl -ne 'while ( /(("[^"]*"|[^,])+)/g ){ print("$1\n") }' Perl にも CSV を扱うモジュールはあるけどね。 ちょっとやろうとしてみたけど _var='a b "a,b" c "a b"' IFS=' ' eval set -- $_var for s in "$@"; do echo "$s" done ↑これが↓ a b a,b c a b になるのに、 _var='a,b,"a,b",c,"a b"' IFS=',' eval set -- $_var for s in "$@"; do echo "$s" done ↑これが↓ a b a b c a b ↑こうなってしまうのでevalとsetでどうにかするのはかなり難しそう。 (コンマの情報が潰されちゃう) シェルスクリプトで自作するのに拘ってるみたいだけど m3u8パーサ?使うべきじゃないかなぁ。 >>443 Perl(PCRE)だと non-greedy matching が使えるからいいよね とすると GNU grep ではこんな感じ grep -Po '((".*?"|[^,])+)' なんかハマってるなw 例えば最初がこれだとするだろ? index=2,INFO1="a bc",INFO2="ab,c" ダブルクォートの中にスペースが入ることがあるとして、まずスペースをありえない文字(制御文字)に変換するだろ? index=2,INFO1="a<DEL>bc",INFO2="ab,c" 次にカンマをスペースにするだろ? index=2 INFO1="a<DEL>bc" INFO2="ab c" これをeval + setするだろ? eval "set -- $DATA" そうすると、こうなるやんか? $1: index=2 $2: INFO1="a<DEL>bc" $3: INFO2="ab c" あとはループして、<DEL>をスペースに戻しつつevalすればOKだよ 文字の置換はIFS使って分割して結合 俺が悩んでたのは、実はありえない文字に変換しないで できないかなーってところなんだよねw >>438 そういうのは仕様。それを防ぎたかったらevalは使えないのでパースするしか無い もしくはエスケープ+evalだけどエスケープするために結局パースが必要になる http://npm.taobao.org/package/m3u8-file-parser に載ってる m3u8 のサンプル を見るとこういう行もある #EXTINF:23.222 tvg-logo="haha, ddd" tvg-aa="sb@" tag=sa, Sample artist, : - Sample title <https://tools.ietf.org/html/rfc8216#section-4.2> ;によるといずれの形式の属性値も読点を含んではならないとあるのに, 例えば<https://tools.ietf.org/html/rfc8216#section-4.3.4.2> ;のCODEC属性値の説明には「引用符で囲まれた読点区切りの…」とある。 もしもAttributeValueの形式に全部のタグが従っていたら,上での細かい話は要らずに IFS=','やらawk -v FS=','やらいくらでも方法はあったのにね。 ざっと見たところ,属性値であるにもかかわらず読点を含むという仕様になってるのは例にも挙げた #EXT-X-STREAM-INF:タグのCODEC属性値のみっぽいので,もういっそそれだけを区別して処理するのもありかも。 中身のない連投すまんが, 処理する相手がRFC 8216に準拠したファイルだという前提があるとするなら タグごとに挙動を変えるほうが賢いかもしれない。 というのもどのタグにどういう文字列が現れうるかということが規格に明記されているので。 >>446 ありえない文字に置換する手法もいいとは思うけど,そういう制御文字ってたいてい <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap06.html#tagtcjh_4> ;に記述されている 非可搬な文字だから,ちゃんと運用する予定のスクリプトに入れるのは不安……。 しっかし音楽・映像関連の処理をシェルスクリプトでやろうとしているとは, そうとう変わってるなw 普通そんなファイルが存在して,かつそれらを自分で処理する=その後何らかの形で利用する ような環境にいるんだったら,もっと色々やりやすい道具(PythonやらJavaScriptやら)もある筈よね。 シェルスクリプトで処理するしかないのは,貧弱な環境と単純なデータ構造に対してでしょうに。 (まあ>>1 で「他の言語でやれ」は禁止とあるから,シェルによる処理を考えているけど) 世の中には「ナントカ原理主義」を標榜する一派がいるのでな… いや、この話題はやめておこう >>449 非可搬な文字ってどういう意味? ただの文字コードに過ぎないし、化けるわけでもなし どんな問題があるのか全くわからんのだけど、 それにそこのテーブルに書いてある文字がダメだというのなら、 ESCAPE文字もダメってことになるじゃんか 16進数で0x1B、8進数で033、 文字に色をつけるときの\033 echo -e "\033[0;31mテキスト\033[0;39m" 理論上でもいいからどんな問題があるのかを言ってくれないと 非可搬な文字を心配するぐらいだったらAWKのGNU拡張に対応してるかを心配するほうがより現実的w >>452 おっしゃる通り理論上の話で実際はほぼありえない(制御文字の使い方もほぼ統一されてるから)けど, <DEL>文字が端末それ自体を制御する為のものだった場合,それが標準出力に出力された時に 端末自体に挙動が渡ってしまう。 > 文字に色をつけるときの... 事実色をエスケープ文字によって付ける方法はシェルの標準には載ってない。 >>454 別に<DEL>じゃなくてもいいよw 略称思いつかなかっただけだし、表示されて困る文字だからこそ テキストの中に含まれてることはないだろという理由だし > 事実色をエスケープ文字によって付ける方法はシェルの標準には載ってない。 シェルの標準の載ってるかどうかの話じゃなくて「非可搬な文字」だから「使えない」という 理屈でいくのなら、エスケープ文字も使えないねって話 俺は「非可搬な文字」だけど「使っていけないとは書かれてない」と言ってる だいたい非可搬っていうのは、その文字の意味が定められていないぐらいの意味やろ バイナリで見ればただのデータなんだから バイナリで見ればこのバイトは非可搬な文字と一致するから データの中に使ってはいけないんだ〜みたいな話したいわけじゃないやろ? >>455 いや,別に<DEL>に限った話じゃない。 今回みたく 「シェルに扱ってほしくない文字を置換して一時的に退避」 →「シェルで処理」→「元に戻す」 ↑こういう手法を使うにあったって必要な, 「普通の文字列には現れそうにない文字」 っていうのは大抵不可視の制御文字でしょう?(<DEL>だろうが<US>だろうが<FS>だろうが) で,そいつら制御文字が標準出力に流れた時の挙動は未定義だから避けたほうがいいんじゃない? という話。 繰り返すけど,これは理論上の話で,実際はほぼ起こり得ない。 けれども, printf '\033[>c' | cat ↑こういうスクリプトが実行されたとすると,こいつはある種のOS/端末で端末情報を返すので パイプも働かないし,おかしなことになる。 しつこいけど,こんなことが意図せず起きるなんて万に一つ。 普通は<US>やら<FS>やらを一時退避用の制御文字として利用するし,こいつらはOS/端末に対してなんら特殊な働き掛けをしないのが通例だからね。 ただ,しないとも限らないし,そうでないことが規定されておらず「非可搬」だと明記されていることも踏まえると,使わないほうがいいかなと。 >>456 > で,そいつら制御文字が標準出力に流れた時の挙動は未定義だから避けたほうがいいんじゃない? いやだから、そういう理屈でいくと、 「色をつけるエスケープ文字も避けたほうがいいんじゃない?」って 言ってるってことでいいんだねって聞いてるんだが Ruby にも、CSV モジュールがある デフォルト設定では、 行区切り文字は、改行 列区切り文字は、カンマ クォート文字は、" この3つの特殊文字が、要素内にない時は、クォートしなくてよい 逆に、ある時は、クォート文字で囲む。 その際、" だけは、"" と2つにする! >>458 話の流れが分からない馬鹿は引っ込んでろ csvパーサー使えで終わる話を 延々とやってる暇人のほうがどう考えても馬鹿だと思うぞ >>457 うん。色を付けるエスケープ文字も,可搬な規格がない以上避けたほうがいい。 もちろん,ISO 1745やらに従って着色するという手もあるけど IEEE Std 1003に準拠してる処理系がISO 1745にも準拠してるとは限らないからねぇ。 >>460 今の話はCSVの話じゃないよ,HTTP Live Streamingのファイル形式。 これはCSVの規格と違うもの。 じゃあ可搬な規格がない文字を出力する POSIX標準のtputはアウトだねw 可搬な規格がない = 使ったらダメって考えなんでしょ なんで可搬な規格がないから使ったらダメになるのかさっぱりだw >>463 どうやったら「避けたほうがいい。」が「使ったらダメ」になるんだ? 読んでるこっちの方のセリフだよ>さっぱりだ >>464 非可搬な文字だから,ちゃんと運用する予定のスクリプトに入れるのは不安 なんでしょ?その不安を解決するには禁止するしか無いじゃん だいたい最初に聞いたはずだが、一体何がポータブルじゃないのかって。 ポータブルじゃないのはその文字を端末に表示した時の端末の挙動であって、 その文字を使ったときにシェルが誤動作するとかいう話ではまったくない そもそも今回は画面に表示しないから全く関係ない。 スクリプトはどんな環境でも正しく動くのに避ける理由がない。 画面に表示した時の端末の挙動の話であることをあんたは理解してない 文字自体はポータブル(そもそもただの値でしか無い) シェルスクリプトで使えないデータは 0x00 のみ(zshなど一部シェルでは使えるようだが) × 画面に表示した時の端末の挙動の話であることをあんたは理解してない ? 理解したふりして本質的な所が分かってない。理解が浅いから 話がつながってることが分かってない。それぞれ単独に知ってるだけ。 >>465 不安なのは俺であって>>464 ←こいつじゃない。 そこはちゃんと見ろよ。相変わらずオッチョコチョイな奴だw シェルスクリプトでC言語みたく do {...;} while () 的な書き方できないかな。 つまり最初に条件無視して絶対一回実行されるっていう。 while true; do do_something condition && break done while do_something condition do :; done do {...;} while () はいらない子 >>475 たしかにCでも>>472 氏や>>473 氏のような手法で while (...) { ...; } 文で実現できるな… 縁の下の力持ちだよ。 /usr/include で grep してみなさい。 wc -mがUTF-8とかの文字列でも正しく判定できててビビった。 GNU系はともかく組み込み向けの実装では 絶対無理だと思ってBusyboxとかで試したんだけど、 全部正しい文字数を数えれてた……。 寧ろ喜ぶべきなんだけど、なんか釈然としない(foldとかがポンコツなのに) 逆にbusyboxは動くやろw 不安なのはBSDやで、 あれ、それなりにOKだったらそこで終わってるやん POSIXの最低基準さえ満たせればいいって思ってる。 busyboxはPOSIX完全準拠を目指さない代わりに 「現実的な用途で動くこと」を目指してる。 UTF-8対応も現実的な要件の一つだよ fold -w n に関しては LC_CTYPE=ja_JP.UTF-8 grep -Eo '.{1,n}' とかにするとか Windows版busyboxも日本語処理なんとかしてくれないかなぁ。 cp932の処理がいまいちなのか、コマンド・プロンプトで使うlsでダメ文字のファイルが表示されないよ。 >>481 Windowsのネイティブ文字コードはUnicodeなのだから cp932を使うのをやめればいいだけ >>482 cp65001 だと文字化けして使えない >>483 powershell で busybox ls とやっても同じくダメ文字が表示されない 最新のバイナリ(busybox-w64-FRP-3329-gcf0fa4d13.exe)でもだめ なんで対処方法お母さんに聞かなかったの? 自分で対応できると思ったの シェルスクリプトでaliasを使うことでしか実現できない挙動ってある? コマンドを別に定義する方法って主に3通りくらいある 関数: somecmd() { ... } 別名: alias somecmd=... 変数 : somecmd=... と思うんだけど、この内aliasに独特の特長ってあるのかな。 >>478 UTF-8は上位ビットを見れば文字の先頭か途中かまた何バイトなのか等がわかるので変換しなくても文字数はわかる(詳しくはWikipedia等を参照)。 そんな小技使って作られているかどうかはわからないが。 >>488 alias loop="while true; do" loop echo aaa; done alias IF=if alias THEN=then alias ENDIF=fi IF [ a = a ]; THEN echo aaa ENDIF >>490 一応変数使ってもいけね? loop='while true; do' eval "$loop echo aaa; sleep 0.1; done" てかeval使えばなんでもありだから, evalを使わずにって条件だと,挙げてくれた例みたいなことが 実現できるのかな。 × 一応変数使ってもいけね? ○ eval使ってもいけね? だろ >>492 loop() { while true; do "$@"; done } f() { echo aaa; sleep 0.1; } loop f shebangにさ、#!/bin/sh -eu って書いたらちゃんと動くのに、 #!/bin/sh -e -u って書いたら動かない オプションは一つしか受け付けない? これってどこに仕様ありますか? 一つしか受け付けないと言うか #!/bin/sh -e -u って書いたら /bin/sh "-e -u" って解釈されるのか 全体が一つの引数 実はshebangの決まった仕様はないからOS依存 >>500 仕様上はOS依存として、 実際にこれ以外の挙動をする場合ってあるの? >>488 \ でalias をキャンセルできる機能 関数とか変数では、例えば ls を定義したときに 簡単にキャンセルできない。alias なら $ \ls で一発O.K. >>502 command なら alias も function も OK $ command ls >>501 a) 1つ目のスペースの前がコマンド名、その後はスペースも含めて1つの引数 (Linux等) b) 1つ目のスペースの前がコマンド名、その後はスペース区切りの複数の引数 (昔のBSDやOSX等) c) スペースも含めて全部コマンド名 (実在するか不明) d) shebang非対応 (昔はあったがほぼ絶滅) あとは、最大長とかにも注意 >>505 #!の次は本来スペースだって知ってた? >>478 Windows10, WSL, Ubuntu 18.04 では、 中国の「深圳」みたいな、サロゲートペアも、1文字になる! echo -n '深圳' | wc -m 2 >>507 https://www.in-ulm.de/ ~mascheck/various/shebang/#blankrequired によるとその話が正しい証拠はない模様 >>507 逆にスペースを入れてはいけないというふうに教わったけど、 入れたからといって動かないというのはないな。 >>510 オライリーのシェルスクリプトの本には 一部のBSD系OSで#! の後にスペースが要るみたいなこと書いてあった。 でも、これは又聞きで全部試した訳じゃないけど そんな挙動のBSD実装はなくて、 実はGNUプロジェクトのソースコードに誰かが勘違いして書き込んだコメントが元らしい。 >>505 > b) 1つ目のスペースの前がコマンド名、その後はスペース区切りの複数の引数 (昔のBSDやOSX等) macOSが今もこれなんだな。複数の実装があるのはめんどくさいな >>512 ソースチラ見した限りでは元々は a) ぽい。# の後ろはコメントとして切り捨ててるみたいだが FreeBSDをガシガシ取り入れた時にFreeBSDが b) だからに変えたぽいかな。その後FreeBSDが a) に変わったが追従せずな >>513 ># の後ろはコメントとして切り捨ててるみたいだが 元々はこれもなく、まんま a) 。その後に #の後ろ切り捨て。その後 b) だった macOSでshebangにダブルクォートが入っていた場合どうなるんだろうなぁ すぐそこにマシンあるから調べればわかるけどさw 一番古い10.0から公開されてる最新の10.4までで、そこでダブルクォート文字は現れない、'\n'、'#'、' '、'\t' ぐらいしか文字としてナニかを判断してない 単なる文字だね。そのまま引数としての単なる文字として なんか説明しようとしたんだがな ダブルクォートが入っていても関係ないよ。なぜかは調べてね >>518 悪い文化というより、POSIXで規定しろというだけかな 悪い文化のががっつりカーネルで実装されてるんだけど ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる