X



シェルスクリプト総合 その37

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
垢版 |
2021/10/05(火) 22:49:30.91ID:KsbWuyFp
シェルスクリプトに関する総合スレッドです。

全般
・荒しは無視しましょう。
・丁寧な姿勢を心掛けましょう。
・ネチケット(死語)を意識しましょう。
・「○○(他の言語)でいいやん」は禁止。他のスレに行ってください。
・「POSIX原理主義」「ユニケージ」「USP研究所」はPOSIXとUnixを曲解し
間違ったシェルスクリプトを広めている宗教です。洗脳されないようにしてください。

前スレ: シェルスクリプト総合 その36
https://mevius.5ch.net/test/read.cgi/tech/1614212414/

関連スレ
・【Bash】Windows Subsystem for Linux【WSL】11
https://mao.5ch.net/test/read.cgi/linux/1627507889/
・Bashでプログラミング [転載禁止](c)2ch.net
https://mao.5ch.net/test/read.cgi/linux/1443885102/
・シェルスクリプト総合 その28
https://mevius.5ch.net/test/read.cgi/unix/1533154936/
・zsh その7
https://mevius.5ch.net/test/read.cgi/unix/1337844883/
・過去UNIXで使われていた ksh というシェルについて
https://mevius.5ch.net/test/read.cgi/unix/1582358403/
・【POSIX】UNIXプログラミング【BSD】 [転載禁止](c)2ch.net
https://mevius.5ch.net/test/read.cgi/unix/1443103705/
・おまえら! shell は何を使っているんですか?
https://mevius.5ch.net/test/read.cgi/unix/1012330865/
0614デフォルトの名無しさん
垢版 |
2022/02/04(金) 02:08:49.30ID:CBYs6kse
awk -v "var=`grep -A 1 'guid: c5b' source.prefab | sed -n '2p'`" '{ sub(var, "hello, world!"); print }' source.prefab > after.prefab
0615デフォルトの名無しさん
垢版 |
2022/02/04(金) 05:17:13.50ID:QBYNvY3/
>>612
なんかものすごくイキってるみたいだけど
まともに動くコード書いてからにしてねw
0621デフォルトの名無しさん
垢版 |
2022/02/04(金) 09:33:54.99ID:tCsz8H1O
sedやawkつかうならperlつかうな
シェルスクリプトなんだから、判定等はそちらに任せて
あくまで置換等の処理限定で
0623デフォルトの名無しさん
垢版 |
2022/02/04(金) 09:56:25.32ID:mTUPlCRU
>>600
sedの-zオプション使って複数行まとめて置換すれば?

sed -Ez 's/(guid: c5b2e3eb25e32904fa18c5ae09b782d9[^¥n]*¥n m_Name: )¥n/¥1FOOBAR!!¥n/g' ServerCameraSpot.prefab
0624デフォルトの名無しさん
垢版 |
2022/02/04(金) 09:57:49.27ID:tCsz8H1O
柔軟性のないsedや、ハードル高めのawkよりいいべ
シェルスクリプトができる環境ならだいたいperlは入ってるし
0625デフォルトの名無しさん
垢版 |
2022/02/04(金) 10:32:37.85ID:bISwOsTB
条件の行と処理したい行が分かれてる時点で単純なフィルタじゃ無理だからでしょ

awkなりperlなりで状態遷移は必須

むしろsedでできるなら教えてほしい
0627デフォルトの名無しさん
垢版 |
2022/02/04(金) 11:10:04.73ID:+I1ORxpE
たくさんのレスありがとうございます、試してみます
0628デフォルトの名無しさん
垢版 |
2022/02/04(金) 11:26:16.31ID:NXJAfnlz
あっさりワンライナーで書かれたもんだから激おこですな
0633デフォルトの名無しさん
垢版 |
2022/02/04(金) 12:54:29.42ID:mTUPlCRU
ワンショットならsedで十分なのかもしれないけど
同じタスクがまた発生しそうならunity yaml用のツール作っておくほうがいいと思う

from unityparser import UnityDocument

doc = UnityDocument.load_yaml(‘ServerCameraSpot.prefab’)
entry = doc.get(class_name='MonoBehaviour', attributes=('m_Script',))
for k, v in entry.m_Script.items():
 if k == 'guid' and v == 'c5b2e3eb25e32904fa18c5ae09b782d9':
  entry.m_Name = "FOOBAR!!!"

doc.dump_yaml()
0634デフォルトの名無しさん
垢版 |
2022/02/04(金) 12:58:11.93ID:NMPx/TbP
>>612
そんなのただのawkのベタ書きじゃねーか
ベタ餓鬼するなら断然perlのほうがいいよね

cat ServerCameraSpot.prefab | perl -ne '
if (/guid: c5b2e3eb25e32904fa18c5ae09b782d9/) {
chomp($a=<>);
print "$_$a new\n";
} else {
print
}'

perl最強!
0637デフォルトの名無しさん
垢版 |
2022/02/04(金) 13:51:48.01ID:mKMsSnzj
Ruby のyaml を使ったら、最初のPrefab 部分しか取れなかった。
行頭に、--- があって、複数の文書として扱われるからかな?

require 'yaml'

data = YAML.load_file( "ServerCameraSpot.prefab" )
p data

出力
{"Prefab"=>{"m_ObjectHideFlags"=>1,
"serializedVersion"=>2,
続く
0639637
垢版 |
2022/02/04(金) 14:34:10.41ID:mKMsSnzj
Ruby のyaml で、load_stream で複数文書を読めるらしいが、
14行目の、--- !u!1 &1459795647327810 で、エラーになる

found undefined tag handle while parsing a node at line 14 column 5 (Psych::SyntaxError)

require 'yaml'

File.open "ServerCameraSpot.prefab" do |io|
p docs = YAML.load_stream( io )
end
0640デフォルトの名無しさん
垢版 |
2022/02/04(金) 14:43:47.14ID:u7GqER63
>>638
5ch仕様なのか連続複数スペースは一つにまとめられるみたいね
m_Name: ) の前のスペースが一つになっちゃってる
0641637
垢版 |
2022/02/04(金) 17:49:45.92ID:mKMsSnzj
Unity は、UnityYAML と呼ばれる、独自に最適化された、YAML ライブラリを使用します。
UnityYAML ライブラリは、完全な YAML 仕様をサポートしません

--- で始まる行を、--- に置換すると、Ruby のYAMLでも動いた

require 'yaml'

# 行末の改行を削除して、1行ずつ処理する。accum は蓄積変数
input_yaml = File.foreach( "ServerCameraSpot.prefab", chomp: true ).with_object( String.new( ) ) do |line, accum|
line = "---" if line.start_with?( "---" )
accum.concat( line, "\n" )
end

docs = YAML.load_stream( input_yaml ) # 複数文書
p docs.dig( 1, "GameObject", "m_Name" ) #=> "ServerCameraSpot"
0642637
垢版 |
2022/02/05(土) 12:59:45.97ID:Wxa6LWM/
>>641
の最後の行を、コメントにして、
# p docs.dig( 1, "GameObject", "m_Name" ) #=> "ServerCameraSpot"

その後ろに、下の2行を付け加えると、内容を変更して出力できる。
docs[ 3 ][ "MonoBehaviour" ][ "m_Name" ] = "あいう" # 変更
puts YAML.dump_stream( *docs ) # 複数文書

ただし最初の、% で始まる、2行のディレクティブが出力されない。
それと、複数文書の区切りが、--- となる

--- !u!1001 &100100000
みたいな、Unity の型を、Ruby では解釈できない

UnityのYAMLは正規形じゃないから、普通のパーサーで解釈するのは、骨が折れる
0643デフォルトの名無しさん
垢版 |
2022/03/01(火) 06:59:09.07ID:/KEw0dOm
timeコマンドみたいな感じで、あるプロセスとその子プロセスが読み書きした
ファイルのデータ量を簡単に調べる方法ないですかね?

Linux板に書き込めなかったのでここで
0644デフォルトの名無しさん
垢版 |
2022/03/01(火) 07:24:58.47ID:2BqTSfQO
俺が知らないだけかもしれんが、コマンドとしてはないんじゃないかな?
mmapのメモリコピーによる書き出しの捕捉はカーネル空間じゃないと無理だろうし
比較的簡易的なのはstraceだけど、mmapのは漏らす
面倒なのでstapとか思いつく
0647デフォルトの名無しさん
垢版 |
2022/03/01(火) 21:44:05.39ID:84NGcGuL
Linux 板は、荒らし退治がすごい

もう何か月も書けない。まだ、何年も続きそう
0648デフォルトの名無しさん
垢版 |
2022/03/01(火) 21:55:02.49ID:84NGcGuL
「linux メモリ使用量 プロセス 監視」などで、検索すれば?

Zabbix などに、そういう項目は無いのか?
0653デフォルトの名無しさん
垢版 |
2022/03/25(金) 23:16:30.56ID:ztMhdJXY
久しぶりにこのスレ来たけどPOSIX云々言ってた人消えたんだな
一気に過疎ったな
0656デフォルトの名無しさん
垢版 |
2022/03/26(土) 04:10:35.39ID:fJwm7Jgq
一時期は数ヶ月で1スレ消火するぐらいの勢いがあったのに。つわものどもが夢の跡
0658デフォルトの名無しさん
垢版 |
2022/03/29(火) 09:16:04.55ID:3XcWZYBt
見てきたけど酷いな。よくシェルショッカーなんて相手にするよ
リッチー大佐も冷静を装ってるが完全に脅迫になってるのわかってないのかな
0660デフォルトの名無しさん
垢版 |
2022/04/05(火) 15:31:19.76ID:0XOZrJsf
昔は、マクロでCを他の言語っぽく書けるようにする、つー流派?があったからなあ。w
begin/endを定義してPascalっぽくとか。
0663デフォルトの名無しさん
垢版 |
2022/04/06(水) 16:06:26.14ID:S7CGIPqQ
doが対称性を崩してるよな
キーワード …; do

done

FOR-ROF
LOOP-POOL
WHILE-ELIHW
美しい対称性
0664デフォルトの名無しさん
垢版 |
2022/04/07(木) 16:39:39.21ID:pi20fczf
xargs コマンドの -P オプションに、3時間ぐらい前に気付いた。
0665デフォルトの名無しさん
垢版 |
2022/04/11(月) 13:29:24.85ID:KjtEvxV7
>>659
#define POOL }
これやったことあるわ…
cの式とbrainf**kの命令は一対一対応してるので、main()内にそのまま展開すればbfトランスパイラになる
これそのままで動く

https://en.m.wikipedia.org/wiki/Brainfuck

brainfuck command C equivalent
(Program Start) char array[30000] = {0}; char *ptr = array;
> ++ptr;
< --ptr;
+ ++*ptr;
- --*ptr;
. putchar(*ptr);
, *ptr = getchar();
[ while (*ptr) {
] }

大体合法なCトークンじゃないので、一度BRAに置き換えてsedで置換する必要はあったけど
0666デフォルトの名無しさん
垢版 |
2022/04/15(金) 15:18:31.03ID:LoHMCFtw
bashの
[[ -a ${TMP_FILE} ]] && rm -f ${TMP_FILE}
って-aとか[[ ]] &&とかそれぞれどういう意味なの?
TMP_FILEがあったら消すってことなんだろうけど
0667デフォルトの名無しさん
垢版 |
2022/04/15(金) 16:01:54.46ID:hbtBlxLh
-aはファイルが存在すれば真になるという古い書き方
ANDの意味の-aと間違いやすいから-eを使え
&&は普通にANDだろ
0668デフォルトの名無しさん
垢版 |
2022/04/15(金) 16:05:53.77ID:LoHMCFtw
>>667
古い書き方なのねandの-aと紛らわしいな
0670デフォルトの名無しさん
垢版 |
2022/04/16(土) 09:12:23.33ID:AbnHWb9H
短絡評価。真、偽の順で表示される

and の場合は、左辺が偽なら、右辺を評価せずに、偽が確定する。
or の場合は、左辺が真なら、右辺を評価せずに、真が確定する

[ a = a ] && echo 真
[ a = b ] && echo 表示されない

[ a = a ] || echo 表示されない
[ a = b ] || echo 偽
0671デフォルトの名無しさん
垢版 |
2022/04/18(月) 16:18:56.11ID:GGXXVNot
bashは構文を拡張しすぎたせいで、変なのを書くやつが増産されてしまった。
0672デフォルトの名無しさん
垢版 |
2022/04/18(月) 16:20:19.34ID:GGXXVNot
>>668
[]がコマンドであることを認識した方がいい
0674デフォルトの名無しさん
垢版 |
2022/04/18(月) 18:56:00.27ID:IfcMEIPj
>>672
testコマンドってこと?
0675デフォルトの名無しさん
垢版 |
2022/04/20(水) 11:54:29.01ID:e4Ywa9g+
昔は [ が test にシンボリックリンクされていたものぢゃ
0676デフォルトの名無しさん
垢版 |
2022/04/20(水) 17:00:20.67ID:SrakFfBy
ファイルの先頭と末尾だけを表示させたくて
$ (head;tail) < tmp
みたいなことをしててふとハマったんだけど、
$ for i in {00..60};do echo "22-04-20 00:$i"; done > tmp
$ (head;tail) < <(grep 22-04-20 tmp)
だと head 分しか表示されなかった

多分シグナルとかの関係だろう、と思ってるんだけどイケてる回避策ってあるかな?
まあなければ愚直にファイルに書き出すだけなんだけども
0677デフォルトの名無しさん
垢版 |
2022/04/20(水) 17:17:12.72ID:65nfU3ze
たぶんheadが複数行まとめて読み込んで行数とか判断してるんだと思う

回避策はないかな
stdinから読み込む挙動を変えるオプションも無さそうだし
0679デフォルトの名無しさん
垢版 |
2022/04/21(木) 12:40:10.24ID:yp5x7VDG
せやったら全部Sedだけでええやろ!w

と思ったけど、なるほど、むつかしいんやな。。。
末尾複数行を簡単につまめないんやった。
$(($(wc ...)-N))を埋め込んだらできるけど、それもなー。
0680デフォルトの名無しさん
垢版 |
2022/04/21(木) 12:49:57.95ID:zIIL/8l3
どうでもいいけど22-04-20 00:60ってなによ
0682デフォルトの名無しさん
垢版 |
2022/04/21(木) 14:22:25.48ID:zIIL/8l3
年月日ではなく時分のところ
0684デフォルトの名無しさん
垢版 |
2022/04/21(木) 21:22:45.77ID:+ZjRtsOn
readでcsvのヘッダを読んで、本体だけが次のパイプに渡って処理され、最後にcatで再結合する技は見たことある

つまり、head じゃなくて10行readならいけるんでないか?
0686684
垢版 |
2022/04/21(木) 22:14:40.59ID:+ZjRtsOn
>>685
検索力に惚れるわ

俺は過去ログ取得に不快な広告見せられたのでコピペっておく
231 名無しさん@お腹いっぱい。 sage 2017/06/14(水) 11:09:43.34 .net
head -1 じゃなくて read を使ってこんな事をしてたり
df -h | { read h; echo "$h"; sort -k5,5gr; }

そうそうこんなん書いてたわ、例の通りdf -hやtsv/csvのヘッダ一時退避に重宝するイディオム

しかし-nは覚えてるけど行数オプションとかあったかな?
whileで包んで10回数えるのも多分行けるとは思うが、まあ最悪
read line; read line;…
なら通るでしょう()
0689デフォルトの名無しさん
垢版 |
2022/04/22(金) 01:40:46.85ID:p9VEf+/q
lsの日時の書式をyyyy/mm/dd hh:mm:ss固定にしたいのですがどっかに設定あるんでしょうか
0690デフォルトの名無しさん
垢版 |
2022/04/22(金) 02:32:55.95ID:SxzvmxoM
>>688
これ動くような気もするけど、エッジケースの詰め合わせみたいで関心するわ…ぜひ明日試したい

teeはプロセス置換への分配を均等に進めるのか?
head/tail でなければ入力も出力も数ブロックのバッファ単位で入り交じるはずだけど、バッファ単位に収まる10行のhead/tailの出力は一塊で吐かれるはず、つまりhead→tail/tail->headのいずれか
先頭だけ舐めるheadの方がtailより先に処理を終えるからhead->tail、の出力になるのだろうか?
0691デフォルトの名無しさん
垢版 |
2022/04/22(金) 02:54:12.16ID:AtJxm6z2
tee, head, tailの実装とバッファリングモード、入力データの素性の全てに依存してそうなヤバさ
0692デフォルトの名無しさん
垢版 |
2022/04/22(金) 03:06:07.22ID:xNmupzsw
とりあえず手元のandroidとかいう玩具で

GNU bash, version 5.1.8(1)-release (aarch64-unknown-linux-android)

$ seq 100 | tee >(head) >(tail) >/dev/null
91
92
93
94
95
96
97
98
99
100
1
2
3
4
5
6
7
8
9
10
0695デフォルトの名無しさん
垢版 |
2022/04/22(金) 03:34:30.65ID:SxzvmxoM
入力が小さいときに限っては、teeも実質引数に一回渡したきりだからheadの速さも関係ないんだろうね
seqの引数を二分していけば均衡して、結果はランダムになりそう
0696デフォルトの名無しさん
垢版 |
2022/04/22(金) 05:38:09.18ID:rkPZZrpS
awk -v N=10 '{ if (NR <= N) print $0; buf[NR % N] = $0 } END { for (i = (NR - N + 1 > N + 1 ? NR - N + 1 : N + 1); i <= NR; i++) print buf[i % N] }'
0697デフォルトの名無しさん
垢版 |
2022/04/22(金) 09:43:04.69ID:9We3r0d8
つまりさ、複数のコマンドを使って
効率的に処理する方法はないってことでしょ?
>>696みたいにするしかない
0699デフォルトの名無しさん
垢版 |
2022/04/22(金) 11:52:54.17ID:IqSZbuIe
>>689
ls −l −−time−style=+'%Y/%m/%d %H:%M:%S'
をaliasにでも登録しておく
0700デフォルトの名無しさん
垢版 |
2022/04/22(金) 12:15:37.42ID:IW9biBQV
>>697
そもそもgrepが律速なんだから効率とか野暮だけど、あえて言うなら

元のファイルがダンプしてしまえるならストレージは食うが終端にシークしてしまうのが最速だし、ストリーム処理なら初めの10行プリントする自明な処理の後、10行のバッファを保持して終端が見えるまでひたすら読みまくるしかアルゴリズムはないわけで

それはsed N;N;...でもなんでもいいが、timeするまでもなく10行保持して読み捨て専用マシーンとしてガリガリチューンされてるtailを使うのが最速に決まっとるがな
0701デフォルトの名無しさん
垢版 |
2022/04/22(金) 12:22:41.13ID:IW9biBQV
変な流れになってるのは>>688という爆弾に完全に食われてしまったからな…
俺にも挙動が予測不能過ぎて興味が尽きない
0702デフォルトの名無しさん
垢版 |
2022/04/22(金) 12:37:37.28ID:QL3esWpR
>>695
seq 10001 | tee >(tail -10000) >(head -10000) >/dev/null
を実行しても、headが前半、tailが後半と期待どおりに出力されるんで、問題ないんちゃう?
headは頭から行単位に出力、tailは終端に達してから出力、やと思うとそれでいい気もするし。

>>692は知らん!w
0703デフォルトの名無しさん
垢版 |
2022/04/22(金) 12:45:37.78ID:SxzvmxoM
並スペックのx86-64Debian/bash5/coreutils環境で問題のを検証

>>692
うちではseq 100だとheadが勝った、なおheadとtailを交換しても同じ

10000(適当)でも大体同じ結果が出る、そもそも再現性あるの?と思って十回くらい再実行してたら
1 2 3 4 5 6 7 99991 9992 9993 9994 9995 9996 9997 9998 9999 10000 8 9 10
という入り交じるケースを発見したw
0705デフォルトの名無しさん
垢版 |
2022/04/22(金) 13:21:40.45ID:4sYij9Dr
バックグラウンドの割り込み遅延やその時点での負荷が影響するだろうから、エントロピー源に出来るな
もっとも一様乱数に近付けるにはおま環固有の定数を探す必要はあるが

マウスグリグリで乱数吐く/dev/randomと原理的には同じもの
0706デフォルトの名無しさん
垢版 |
2022/04/22(金) 13:48:09.59ID:MIuZAVWA
そもそもteeから非同期に投げたプロセスが順序良く出力することを期待するのがおかしいわけで
何のコマンドでもいいが、それを暗喩する名前のheadとtailというチョイスがツボに嵌まって面白い
というか>>688は狙ってやってるだろ

pidやマウス座標とか拾って改善目指すとかは無粋
0707デフォルトの名無しさん
垢版 |
2022/04/22(金) 14:06:12.36ID:SxzvmxoM
字面とその挙動、足すことも引くことも躊躇われる簡潔さ
完成し尽くされてるよな
今スレのベストコマンド賞にノミネートしたい
0708デフォルトの名無しさん
垢版 |
2022/04/22(金) 14:37:33.47ID:E3Z2WeTR
ユーモア部門なw
プロセス置換がposixで無いのだけが惜しいが、一番面白いワンライナーなのは間違いない
0712デフォルトの名無しさん
垢版 |
2022/04/22(金) 19:07:59.33ID:t4x32peS
もうとっくに解決してるので…
爆弾落としてった誰かが悪い

>>687でいいと思うが、あえて添削するとすれば、まずコマンド置換は不要
grep pat file | { for i in {1..10}; do read line; echo "$line"; done; tail; }

再利用したいならパラメトライズが面倒なブレース展開を避けるべき(パラメータ展開より先)
{1..10} -> $(seq $n)

もちろんwhileでカウントしてもいい、どちらの版も適当なファイルで取り敢えず動作確認済
■ このスレッドは過去ログ倉庫に格納されています

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