X



シェルスクリプト総合 その27
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
垢版 |
2018/05/03(木) 17:54:23.25
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)もしくはPOSIX準拠の互換シェルがデフォルトです。
 bash/zsh/ksh/ash/dash/yash/poshなどの専用機能に依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
 FreeBSDユーザは/bin/shの正体がashなので注意。
・POSIXについてのリンクは https://en.wikipedia.org/wiki/POSIX にまとめられています
 最新の仕様はこちらへ http://pubs.opengroup.org/onlinepubs/9699919799/
 (左上の「Shell & Utilities」 から参照することができます。)
・v7 shに一番近くて、現役(?)のshは、OpenSolaris由来のheirloom sh。
  http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sh/
  http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
 (理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆうな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
 「そういうのはperl使いましょう」と回答するのはやめましょう。
 安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
 質問に対して問題が間違ってるといちゃもんをつけるのもやめましょう
前スレ シェルスクリプト総合 その26
https://mevius.5ch.net/test/read.cgi/unix/1489979246/
0394名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 17:09:28.43
>>390
だから デ ー タ の中の改 行を何かに変 換すると
もとに戻す処 理を 一 行 一 行やらない といけないから
遅くなるって指摘をずーっと前にした
その遅く なる理由を思 いつかなかった んだろ?
0397名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 17:17:21.14
>>394
なんで一行一行なんだか。sedかtrでやりゃええことやん。それが一行一行か?
遅くなる遅くなるって遅くなるに決まってるやん。条件によりそれが妥当かどうかなんてなんでそう否定できるのか不思議でならない
んな速度速度言うなら、Cなりでやればって言うw 遅い遅い言うてるけど、お前のもじゃどうすんの?ってのがさっぱりだな
0399名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 17:22:11.92
>>392
> 「Mika says \"I'm Happy\"」という形にしたほうが処理しやすいでしょう?
今の話はもっと複雑で

「Mika says "I'm Happy
'couse picked up \10."」

という文だったらどうするか?って話なんだけどな。
いやわかるよ。どうすればいいかは。
問題はどうやってそれを実現するかって話

sedやawkに通す前に、変換すんの?
0401名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 17:25:37.95
>>397
sedやtrを使うと遅いfork、子プロセス生成が行われるからね
データ量に比例してその回数が増えるやり方は駄目
1回か固定の数回でできるって言うなら話は別だけど
0402名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 17:26:19.38
>>400
最初だけできてもだめ駄目

これが実現できないと駄目

> syori "a1" "a2" "a3" "a4"
> syori "b1" "b2" "b3" "b4"
> syori "c1" "c2" "c3" "c4"
>
> という風にsyori関数を呼び出したいのです。
0404名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 17:48:10.30
思ったんだが
正規表現でやらずに有限状態機械を作って
if ダブルクオートで始まらない
  コンマを探して終了
else
  ""でない"に続くコンマを探して終了

とすれば解決するんじゃないかな。少なくともRFC勧告に則ってるCSVは。
0411名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 20:50:13.84
>>408
後処理のだぞ。そのデータ中の改行と行の区切りの区別をつけるために最初にータ中の改行を処理して、終わったらデータ中の改行を戻すって話だぞ?
少しは処理を想像そしてからなんか言ったら?すごい近視眼で明後日な文句言う前に
0412名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 20:55:32.25
>>409
CSVじゃないからあって言うのもいるけど、だったらデータはどう表すのだろうな
データ中の改行と行の区切りの改行ってわからなくね?そのためにデータの始め終わりを表す何かが必要でそれが何かを言ってないんだったら、それを " として話をしてもおかしくはないってか、それしかないだろう
なんでそんな近視眼なツッコミばかりやねん
0413名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 20:56:07.54
>>282

GNU awk の FPAT を使ってみる。一論理行のデータ数は4個で固定、という前提。

gawk -v RS='\0' -v FPAT='"(([^,\n]*)|(([^"]|\\\\"|\"\")*))"' \
'function syori(v1,v2,v3,v4){ ## ここで何らかの処理 ## }
{
i=1
while(i<NF){
syori($(i++),$(i++),$(i++),$(i++))
}
}' data.txt
0414名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:03:59.12
>>411
> 終わったらデータ中の改行を戻すって話だぞ?
そのときに全データの改行を一度に戻すとデータの中の改行と
データ区切りの改行の区別がつかなくなってしまうので、
1データずつ処理する=1行ずつsedなどを実行して遅くなるってことには
気づきましたか?
0415名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:29:15.51
>>411
データ中の改行とデータの区切りの改行はどう区別するんだよ。
同じコードだろ。しかもCSVじゃないんだろ?""でくくられてないんだぜ。
0419名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:49:09.09
もうそろそろ、安全な文字に変換するというアプローチ
(例えば>>289のようなもの)が
ムダで効率が悪いってことに気づきませんかね?

もう一回煽りますね?

>>323
正直、そういう解答を出してほしかったね。だせるかなーって思っていたけど
シェルスクリプトでそういうデータを扱うなんておかしいとかのたまうばかり
\x1c(ファイル分離)、\x1d(グループ分離)、\x1e(レコード分離)、\x1f(ユニット分離)は
まさにそういう用途で使うもの。ここの連中の技術力の低下を感じる。
0420名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:49:14.03
もう一から説明しないと、情報処理の基本すらわかってないようなので
バカバカしすぎだけど、

・改行がデータ中とレコードの終わりを示すのが混在している
・シェルスクリプトは基本、改行は改行でしかなく、データ中なんて知らんただの一行=レコードがブッタ切られる
・データ中の改行を他のナニかに変えれば、シェルスクリプトは一行=1レコードと認識する

前処理:データ中の改行だけをナニかに変える
本処理:改行が終端の一行=1レコードを処理する
後処理:ナニかに変えたのを改行に戻す

たった、これだけのことをなぜ理解できないでトンチンカンなことばっかり言うのか。前処理をsedでできるなんて言ったことないぞ(できるかもだが、それはもっと面倒なの俺は考えんw)。後処理はsedでできることは馬鹿でもわかるだろうにぃぃぃ
0423名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:53:10.76
>>420
> 前処理:データ中の改行だけをナニかに変える
> 本処理:改行が終端の一行=1レコードを処理する
> 後処理:ナニかに変えたのを改行に戻す

それは理解しているが、
1. 改行を何かに また 何かを改行にするには、どうやるのか?
2. 変える または 戻す 処理は1コマンドで実行できるのか?

の答えが、1行ずつfork、execしなきゃならないから
データ量に比例して遅くなるって話をしてる
0424名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:55:00.78
>>423
お前にじゃねえよ。お前は面倒なのでいいよw
遅い遅い言っていれば。1行ずつfork、execしなくてもいい方法もあるのにそこには考えが及ばないだろうし
0428名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:58:11.88
>>426
お前馬鹿だわ
U+001EやU+001Fを区切り文字として利用するんだから
わざわざ改行コードなどを使われない文字に変換する必要ねーだろw
0429名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:58:14.56
最初の質問者じゃなかった、何を目的に延々と絡んでるのか意味不明すぎ
できないできないってばかりで
0430426
垢版 |
2018/06/10(日) 22:59:16.28
あ、「安全な文字」っていうのは「通常の用途に使われるけれども日本語圏では滅多に使われない文字」の意味だったのね。
俺の解釈としてはUnicodeに収録されてる四種の区切り文字も「安全な文字」の類に入るからさ。

勘違いしてすまんな
0431名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 22:59:31.44
bash拡張は置換命令あるけど、
POSIXシェルの場合、外部コマンドを呼び出す以外に
置換命令はないんだよ。知ってる?
0432名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:03:46.06
>>430
> 俺の解釈としてはUnicodeに収録されてる四種の区切り文字も「安全な文字」の類に入るからさ。
まさに、ぽか〜んだわw
今度はお前にUTF-8の講釈をしないといかんのか?

Unix系で簡単に使えるUnicodeはUTF-8しかないが
(その他のエンコードは、文字の中にNULL文字が入るためシェルスクリプトで扱えない)

そのUTF-8はASCII互換であるため、U+001EやU+001Fは
ASCIIコードの0x1Eと0x1Fと全く同じであるため、
この文脈で、Unicodeかどうかなんて考える必要ないんだよ
0433名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:05:23.11
>>428
それは元々のデータがそうであるってこと?そんなんだったら別にこのスレで話題にするようなもんじゃないだろう
いつからそんなのが前提になってるねんwなんかムチャクチャぶりが...ww
0435名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:13:46.83
>>433
> それは元々のデータがそうであるってこと?

ちょっと違うな
「元々のデータがそうであってもよい」ってこと

元々のデータ形式について指定はないのだから
(処理するには効率の悪い)CSVデータでもOKだし、
どんなデータでもよい

そのデータ形式も含めて、
どうしたらいいでしょうか?という話だ
0437435
垢版 |
2018/06/10(日) 23:16:17.88
まあ、そのデータもシェルスクリプトで生成はするんだけどな

シェルスクリプト1 → 何らかのデータ形式 → シェルスクリプト2

「何らかのデータ形式」のデータの中に(データ区切りの改行とは別に)
1データの値として改行等が含まれることがあるのでどうすっかなーって話
0438名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:16:40.28
>>432
お前は>>323を引用して
> そういう解答を出してほしかった
と言ってるんだろ? UnicodeはASCIIの範囲ではそれと互換なんだからUnicodeかそうじゃないかなんてどうでもいいだろうが
お前が言ってるのは
「フィールド区切りにはカンマやアルメニア文字ではなくそれ専用に用意されている文字種を使いましょうね」
ってことだろ? なんか間違ってる?
「ポカーン」とするのもいいけれど、その前に文章をよく読め。脊髄反射でレスするな。
0439名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:17:19.92
>>436
> データの改行とそうじゃない改行をどうすんの?どうやんの?

そこをどうするのが質問だって〜の


> Excelから出力したCSVのように一行(?)の中に改行が含まれた
> データを扱うにはどうしたら良いでしょうか?
って書いてあるんだろ
0445名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:21:59.29
>>442
> 初期から出てるだろ

残念 ながら出てない。 \ を安全 な文字に変 換ってことは
つまりデータを 変 換すると言ってる わけだが、
データは 変換(置換)するななってのが
俺の煽ってる内容
0446名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:22:01.17
>>435
CSVのRFCはフィールド・レコード区切りにU+001F/Eを使えなんて一言も言ってねぇぞ
つーかそれこそコンマと改行が区切り文字ですよと言ってる。
そういうデータを扱うことを議論してる時に、横から偉そうな態度で
「データ区切り専用の文字があるんだから元のデータにそれを使うべき」
なんて言われてもなぁ……。
あなたは論理的思考に弱いようだからもう一度同じことを違う言い方で繰り返すと、
「前提を無視した発言は控えてください」
分かった?
0448名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:23:45.97
>>444
代替案は >>323ででている

俺が煽ってる内容は↓これな。おまいらに>>323のような代替案をだせよって言ってる

326 自分:名無しさん@お腹いっぱい。[sage] 投稿日:2018/06/10(日) 08:14:53.42
>>323
正直、そういう解答を出してほしかったね。だせるかなーって思っていたけど
シェルスクリプトでそういうデータを扱うなんておかしいとかのたまうばかり
\x1c(ファイル分離)、\x1d(グループ分離)、\x1e(レコード分離)、\x1f(ユニット分離)は
まさにそういう用途で使うもの。ここの連中の技術力の低下を感じる。
0449名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:24:21.02
>>446
> CSVのRFCはフィールド・レコード区切りにU+001F/Eを使えなんて一言も言ってねぇぞ

この期に及んでなんでまだCSVの話してんの?
CSVじゃないですって何度も言ってるよね?
0450名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:24:54.06
>>448
いやいやいやいやwwダメだこりゃ
なんら代替案にもなってないのだけど。なんかやけに繰り返すなwやっぱり遅々として進まんな。じゃ、お元気で
0452名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:28:24.22
>>450
お前本当に馬鹿だなw

1データの中に改行コードが含まれてるなら、
(データの中に含まれる改行コードではなく)
データの区切りの方を改行コードではなく、
そのために作られた制御文字を使うって話で
代替案になってるだろ

頭硬すぎw
なんで1データを必ず改行コード区切りにしないといけないのか
シェルスクリプトは1行ずつ読み取る(のが得意)ってだけで
データの区切りまで改行コード区切りにする必要はない
つーかこの制御文字がなぜ用意されているかに気づかんの?

いやはや、ここまで言わんと理解できないのか
0456名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:33:06.87
>>455

>>422を書いたのも俺なんですけど?w
readが改行コードでぶった切られるからって、
データ区切りとする必要はありませんよねぇ(にやにや
0458名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:35:13.32
>>454
> なんでこんなに荒れてんのよ

俺様がたどり着いたゴールにおまいらが
どこまでたどり着けるかを試していたらこうなった
0460名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:40:01.41
>>459
トラップでも何でもないよ。
readの-dでできると言われたとき、
それbash拡張だって指摘するのが面倒だから
先に注意してあげただけ
0461名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:43:44.04
>>460
あー、そういうことか。いちおう試してみていたんだけどね。できんの?
後処理が必要ないのでそれができるのなら確かにそうだな
0462名無しさん@お腹いっぱい。
垢版 |
2018/06/10(日) 23:49:44.49
>>460,461
& 遅い君
確かにできるね。っかしいなあw
これができての、後処理が無駄という話なら全然それに異存はないな。変に絡んでいたらすまんかった
0463名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 00:03:29.86
>>461
ん? ようやく理解したのか?
煽りフェーズが終わると途端につまらなくなるなw

普通にできるし、俺はすでに近い形のものを実装している
自分の用途に合わせて最適化してるんで、汎用的にはなってないがな
(その後に>>282を質問という形でおまいらに問題を出したのだよ)

最初はデータの方をエスケープしてたんだが目に見えて遅くなってな
エスケープの方式をシェルビルトインのprintfでアンエスケープ
できるようにもしたが大した効果はなかった。

そこで制御文字を眺めていたら、その用途ピッタリの文字を見つけたのだよ

データとしては、0x1F(US: Unit Separator)を各項目の区切り(CSVでいうカンマ相当)
0x1Eを(RS: Record Separator)を名前の通り、データ区切りとして使ってる
USの方はIFSを使うことでPOSIX準拠でforなどで処理することができる

さらに0x1D(GS: Group Separotor)を使えば階層構造があるデータを取り扱えるだろうし
0x1C(FS: File Separator)を使えば標準入力で複数のファイルを渡すようなこともできるだろう

便利だがそれに気づいたのは>>323が最初。
おまいらは最初、シェルスクリプトで扱うもんじゃないとか言っていた
>>323のあともその使い道に気づかないでいた。まだまだだなw
0465名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 00:15:39.42
おまけで、一つだけ>>431に補足しておいてやろう
(もちろん>>431を書いたのも俺だけどなw)

> bash拡張は置換命令あるけど、
> POSIXシェルの場合、外部コマンドを呼び出す以外に
> 置換命令はないんだよ。知ってる?

置換命令は無いが、fork相当のことをせずにprintfも使わずに
エスケープされた文字をアンエスケープする方法はある

例えばエスケープの方式がよくある\記号を使うやり方だとして、
IFS='\' (エスケープが必要だったかも知れない)でデータをsplitして
caseで n*) なら改行を表すエスケープ文字と解釈して
一文字目のnを ${STRING#?} で削除しつつ、
改行コードを一文字目に加えるという方法だ

これはこれで遅くなるので却下したんだがなw
0468名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 00:20:59.85
>>466
もう人は俺がたどり着いた答えとは別の
もっといい案が出るのではないかと思って
先入観を与えないために、あえて俺がたどり着いた答えを出さずに
質問の形でかいた。

しかし、俺がたどり着いた答えに辿り着く前に
諦める奴らばかりだった。情けないなw
0474名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 01:13:05.93
たしかにリッチー大佐は酷い人格だけど間違ったことは言ってねえし
しかも有用なツールを作ってから、ああいう毒を吐いてる。
上で喚いてるなんの解決策も出さず人を否定し馬鹿にすることしかできない人間と比較するのは失礼千万
0478名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 01:42:28.78
見た目でわかる文字列への置き換え派ですが、いにしえのエスケープコードの流用はいいアイデアだと思いました。
0480名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 02:22:50.42
>>479
俺は書かないよ。だけどこのスレを参考にして誰かが書くかもしれないね。
その場合、このスレを参考にしましたって書いても書かなっくてもいいよ
他の誰かがこことは別に思いついて書くかもしれないけどw
0484名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 03:07:25.04
ん? シェルスクリプト総合でしょ?
質問スレじゃないし
シェルスクリプトの話題で楽しめばいいじゃん?
0486名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 03:44:51.73
確かにそれ専用の文字があるならそれを使ったほうがいいね。
some data␟other data␟42␞
some data␟other data␟42␞
↑こういうの。
既にそういうフォーマットがあってもいいと思うけどざっと検索したところでは見付からない。
なにか不都合でもあるのか、単純にU+001E/Fの知名度が低すぎるのか。
ところでPOSIX awkはRsやFSに任意の文字って指定できたっけ。GNU awkではできたんだけれど。
0489名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 06:07:49.77
つまらない点だから指摘していなかったが、
この話で U+ という表記はだめだぞ
U+ というのはUnicodeの話で+の後の16進数は
文字集合におけるコードポイントだ

U+001Eは符号方式がUTF-8だと0x1Eになるが、
UTF-16だと 0x00 0x1E(ビッグエンディアンの場合)
もしくは 0x1E 0x00 (リトルエンディアンの場合) となる

U+ だとUnicodeという文字集合を表すことになるが
符号方式がUTF-8だと決めつけることはできない
0490名無しさん@お腹いっぱい。
垢版 |
2018/06/11(月) 09:45:54.74
あほか
最初に本データの形式仕様から制定してもいいという条件を書かないから
みんな処理元のデータ形式は弄れない前提で答えてるんやん

説明不足なのに自分だけ神視点でお題気取りか
死ぬほど痛々しいわ
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況