X



シェルスクリプト総合 その30
■ このスレッドは過去ログ倉庫に格納されています
0626デフォルトの名無しさん
垢版 |
2019/08/07(水) 15:11:31.23ID:3XS5MIC7
どうでもいいけどアレを「完璧な回答」とか言ってる時点でお察しw
ファイルディスクリプタを使った方法にはPOSIXの範囲では解決できない重大な落とし穴がある。
まあ態々言わなくても分かるだろうから,明言はしないがw
0627デフォルトの名無しさん
垢版 |
2019/08/07(水) 15:23:56.01ID:3XS5MIC7
ああ一応分からん人の為にヒントをいうと,実は2018年あたりの過去スレで言及してる。
0628デフォルトの名無しさん
垢版 |
2019/08/07(水) 18:34:55.40ID:WK8NJ3/V
※その落とし穴がなんなのか言わないのは、わからん人のためよりも
俺に意地悪をすることを選んだから。結局それがそいつの本性なんだよ。
0629デフォルトの名無しさん
垢版 |
2019/08/07(水) 19:38:28.14ID:DcvmRDxD
{{"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コマンドを使っても上手くいかず……
0631デフォルトの名無しさん
垢版 |
2019/08/07(水) 19:46:34.34ID:WK8NJ3/V
1行ずつループで回してもできそうだが、なんどもjqコマンドを呼び出すことになって
時間がかかりそうだから、
[
1行目 ,
2行目 ,
3行目 ,
4行目
]

みたいに変換して、jq一発にしたほうが速いだろうな。
そのやり方は、俺以外でも答えられるやろ?
0632デフォルトの名無しさん
垢版 |
2019/08/07(水) 22:04:49.28ID:fPg/gK/3
>>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
0633デフォルトの名無しさん
垢版 |
2019/08/08(木) 02:47:04.99ID:/tBUMiMq
これは、Ruby で、JSON.parse できない。
何や、この形式は?
{"item1":["key1":"value1"]}

[ ] の中に、{ } を入れたら、OK だが、
{"item1":[{"key1":"value1"}]}
0634633
垢版 |
2019/08/08(木) 03:01:29.15ID:/tBUMiMq
https://jsonformatter.curiousconcept.com/

このサイトで、JSON の形式が正しいかどうかチェックしたら、エラーになった!

{"item1":["key1":"value1"]}
Error:Expecting comma or ], not colon.
0636デフォルトの名無しさん
垢版 |
2019/08/08(木) 06:10:00.05ID:l7k6B2kQ
>>629
{{"item1":["key1":"value1"]}}
じゃなくて
{{"aaaa":["bbbb":"cccc"]}}
でも
"cccc" って表示されるけどOK?

あと {{"item1":["key1":"val\"ue1"]}}
みたいに " がデータに入ってる場合はあるの?

それと key1、key2、key3 ってキー名が変わるのは正しいの?

jsonlとしても正しくないけど、書き間違いじゃないの?
0637デフォルトの名無しさん
垢版 |
2019/08/08(木) 07:06:18.58ID:DLp++heI
>>629
これJSONじゃないしフォーマットおかしいってだけじゃね?
正しいJSONならjqだけでcsv変換できるぞ
0638633
垢版 |
2019/08/08(木) 07:20:32.75ID:/tBUMiMq
JavaScript で、: は、オブジェクトの属性だろ。
だから、{ } 内でしか使えない

だから、1 はダメで、2, 3 はOK

1. {"item1":["key1":"value1"]}

2.1 {"item1":["value1"]}
2.2 {"item1":["key1","value1"]}

3. {"item1":[{"key1":"value1"}]}
0639デフォルトの名無しさん
垢版 |
2019/08/08(木) 07:25:15.97ID:l7k6B2kQ
フォーマットが不自然なんだよな。独自フォーマットなら
その仕様を言ってくれないと答えようがない。
例えば、そこに書いてあるキー以外も存在するのか?とか
改行はどうなってるのかとか
0640デフォルトの名無しさん
垢版 |
2019/08/08(木) 09:21:44.35ID:rLFqUIXU
>>629は「中途半端なjson」と言ってるから分かってる気はするけど、
半可通な上司か先輩がJSONを分かったつもりになってるだけで
仕様なんかちゃんと考えて無いと思うなw
0642デフォルトの名無しさん
垢版 |
2019/08/08(木) 11:39:13.74ID:/tBUMiMq
独自形式など、作るだけ無駄

パーサーを作るにも、特殊文字のエスケープ処理など、バグが増えるだけ!
0643デフォルトの名無しさん
垢版 |
2019/08/08(木) 11:47:10.43ID:FeKpuToe
昨日質問したものですが中途半端に書いてしまい申し訳ありませんでした
まだ勉強不足の学生でして……
こっちが正しいjsonと出力させたい内容です

{"aaa":{"bbb":["ccc"]},"xxx":{"yyy":["zzz"]},"あああ":{"いいい":["ううう"]}}
{"aaa":{"bbb":["ccc"]},"xxx":{"yyy":["zzz"]}}
{}
{"aaa":{"bbb":["ccc"]}}



aaa,xxx,あああ
ccc,zzz,いいい
ccc,zzz,
,,
ccc,,
0646デフォルトの名無しさん
垢版 |
2019/08/08(木) 12:28:53.27ID:FeKpuToe
連レスすみません
例えばaaaとあああだけ抜き取りたい場合
さきほどのjsonlから

aaa,あああ
ccc,ううう
ccc,
,
ccc,

と表示させる方法も知りたいです。
全部表示させた後にawkで削除した方がいいのでしょうか?
0648デフォルトの名無しさん
垢版 |
2019/08/08(木) 12:46:24.42ID:0w2TiazL
>>643
学生なら先生に聞けばいいじゃん。
宿題?それでも先生に聞いていいんだよ。

まあ、ここでは丁度良いお題にもなるから良いかも知れないが、宿題の提出期限とかそちらの都合は無視されるよ。
0651デフォルトの名無しさん
垢版 |
2019/08/08(木) 14:01:33.05ID:SmETYGNQ
>>650
おおおおお!!!ありがとうございます!!!
自分がやったときは完全一致してないとエラーが起きてましたのでありがたいです
今後はROMってもっと勉強します
0652デフォルトの名無しさん
垢版 |
2019/08/08(木) 14:03:20.11ID:l7k6B2kQ
なるほどjqコマンドだけでやるにはこうすればいいのか

jq -r -s '["aaa","xxx","あああ"], (.[] | [.aaa.bbb[0], .xxx.yyy[0], ."あああ"."いいい"[0]]) | @csv' data.jsonl
0653631
垢版 |
2019/08/08(木) 14:04:54.81ID:l7k6B2kQ
>>635
すげえだろ?
0655デフォルトの名無しさん
垢版 |
2019/08/08(木) 14:16:46.09ID:SmETYGNQ
今調べてみたら
.aaa.bbb[]と入力していたので全部一致してないとエラーになってたっぽいです
.aaa.bbb[0]に変えている>>650では一致してないところも空欄で出力されてましたので求めるものでした
0660デフォルトの名無しさん
垢版 |
2019/08/08(木) 14:45:49.24ID:PRJfiUWC
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,
って出力しかできぬ
0661631
垢版 |
2019/08/08(木) 14:50:06.59ID:l7k6B2kQ
>>660
あんたが可変長引数を綺麗に勝利できないだけ

printf '%s,' a b c
a,b,c,
0662631
垢版 |
2019/08/08(木) 14:50:53.94ID:l7k6B2kQ
printf 'x%sz,' a b c d e
xaz,xbz,xcz,xdz,xez,
0663デフォルトの名無しさん
垢版 |
2019/08/08(木) 14:55:38.24ID:X/CTiqlR
>>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
0664631
垢版 |
2019/08/08(木) 15:01:30.29ID:l7k6B2kQ
ぶっちゃけ $@ を使ってどうやれば
xa b c d ez, が出せるんだろうって悩むレベルw
0665デフォルトの名無しさん
垢版 |
2019/08/08(木) 15:10:54.30ID:PTwvjoI/
$ 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"

としても可。
0667デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:25:37.21ID:cY5mPUh7
>>660

これを1まとめの変数にする方法ってあるか?

bash test.sh a b c d 

って打つと↓を変数で使えるようにしたい(最後だけ,を外して)

xaz,xbz,xcz,xdz

ループさせて配列に入れて${test[@]}でxaz,xbz,xcz,xdz,
って出力させることならできたけど最後の,が邪魔で仕方ない
0668デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:27:40.23ID:l7k6B2kQ
> これを1まとめの変数にする方法ってあるか?
あるに決まってるだろ。

自分でやり方を模索しろや

> 最後の,が邪魔で仕方ない

ならつかないようにするか消せばいいだけだろ
0669デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:31:34.31ID:l7k6B2kQ
シェルスクリプト特有のテクニックがわからないならともかく
常識的なやり方すら見いだせないなら適性無いで
0670デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:37:00.79ID:cY5mPUh7
マウント上等!教えてくれ!

${test[@]%,*}でいけると思ったが、これって配列じゃ無理なんか
悔しいねぇw
0672デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:38:45.45ID:10jj0QOT
>>668
こいつ昨日の>>626か?
知識があるのは結構だが偏屈な理由でそれを教えようとしないのは目障りだからやめろ。
公共の場所だ,ちっとは考えて行動しろ。
もしも教えたくないのなら,最初から反応するな。
0673デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:39:41.22ID:l7k6B2kQ
おいおい。IDみろよ。俺は重大な落とし穴があるで
教えんけどなー。みたいなことは言わない。
0674デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:41:43.33ID:10jj0QOT
>>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

どうぞ。
0679デフォルトの名無しさん
垢版 |
2019/08/08(木) 18:52:26.35ID:PTwvjoI/
>>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)
0682デフォルトの名無しさん
垢版 |
2019/08/08(木) 19:04:50.27ID:cY5mPUh7
お前らありがとう

want="$(IFS=,; echo "${test[*]}"}"

ってやったら求めるものが出せた
0684デフォルトの名無しさん
垢版 |
2019/08/08(木) 19:09:41.31ID:l7k6B2kQ
カッコの対応がおかしい。
サブシェルに入れる理由がないわけじゃないが、これで処理終了なら遅くなるだけ
この程度でbash依存するのは無駄。長くなってるだけ
0686デフォルトの名無しさん
垢版 |
2019/08/08(木) 19:14:12.37ID:l7k6B2kQ
${l}${l:+,} は俺もよく使うが、ループで毎回比較処理をすることになるし、
最後に末尾処理をしたほうが、速いんじゃないかなーって
常々思ってしまう。lが二回出てくるから1行が長くなることが多いし
0687デフォルトの名無しさん
垢版 |
2019/08/08(木) 19:53:16.22ID:l7k6B2kQ
試してみたけどやっぱりだ。最後に末尾処理するほうが速い。
dashやkshだと2倍ぐらい差が出る。
bashやzshはこういう処理が何故か遅くて差もあまり出ないけど
0689デフォルトの名無しさん
垢版 |
2019/08/08(木) 22:27:17.98ID:/tBUMiMq
Ruby では、Array#join で自動的に、最後の区切り文字を削除してくれる

ary = [ "a", "b" ]

p ary.join( "," )

#=> "a,b"
0690デフォルトの名無しさん
垢版 |
2019/08/08(木) 22:40:09.53ID:X/CTiqlR
そりゃそうだ joinは配列から文字列に変換するときに
間の糊付けをしてくれるのだから
0691デフォルトの名無しさん
垢版 |
2019/08/08(木) 23:05:36.97ID:PTwvjoI/
単純な join でセパレータが一文字なら定番の

$ (IFS=,; echo "$*")

で良いのだろうけど
0693デフォルトの名無しさん
垢版 |
2019/08/09(金) 01:22:55.05ID:sB3SWfXZ
>>688
1行でできるから:+を使いたくなるけどね。
でも変数名が長いと見づらくなっちゃう。

余計なものをくっつけて、最後に削るのは一見無駄なことをしてるように思えるけど
そっちの方が速いってはっきりしたので、これからは気兼ねなく、
:+を使わない方法を使えるようになったよ

>>691
コマンド置換だと遅くなるよ。
IFS=,; echo "$*" でいいでしょ? IFSを戻したいなら戻せばいいだけだし。
それに変数に入れる場合、var="$*" だと最後の改行もちゃんと保存されるけど
コマンド置換を使うと消えてしまう。
0694デフォルトの名無しさん
垢版 |
2019/08/09(金) 01:27:47.18ID:sB3SWfXZ
>>691
> 単純な join でセパレータが一文字なら
という話が出たので、問題。

今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが
それでもIFS=,を使うならばどうすればよいだろうか?

言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、
さてどうすればよいだろうか?
0695デフォルトの名無しさん
垢版 |
2019/08/09(金) 02:31:44.47ID:oVYwNj0v
そんな面倒なことをシェルスクリプトでやるのはやめる
客が7&いじゃなければ大丈夫だろ
0699デフォルトの名無しさん
垢版 |
2019/08/09(金) 03:22:06.84ID:sB3SWfXZ
>>697
とっても無理矢理感があるなw

まず引き数がないときに、xzと表示されるバグが有る。
あと後半意味がわからんw

単純に && printf ',x%sz' "$@" でいいんでないの?
(($#))もいらんし
0700デフォルトの名無しさん
垢版 |
2019/08/09(金) 03:25:55.01ID:sB3SWfXZ
>>698
なるほど。bash依存だとそれができるのか。それは盲点だった。
書いてなかったけど、POSIX準拠の場合はどうなるだろうか?
0701デフォルトの名無しさん
垢版 |
2019/08/09(金) 03:43:31.73ID:tip6m9df
>>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}"; })
0704デフォルトの名無しさん
垢版 |
2019/08/09(金) 04:24:13.39ID:err5h/zJ
>>673
仮に別人だとしても同じようなことしてるぞ。
自分で模索しろとか言って解法を提示していないにもかかわらず
ある程度要求を満たす解法が上がった瞬間それにケチ付けはじめてるじゃん。
もしもほんとうに「自分で模索しろ」って思ってんなら黙っときゃいい話。
わざわざ人が答えを述べてからそれに乗っかるなんてマネする必要ない。
0705デフォルトの名無しさん
垢版 |
2019/08/09(金) 04:28:32.89ID:err5h/zJ
>>700
このコマンドラインをPOSIXに準じたものにするには
(愚直に言えば)単に${VAR/aaa/bbb}をprintf '%s' "$VAR" | sed -e 's/aaa/bbb/'
に変えればいいだけでは?

それかPOSIXの範疇で変数の置換展開を実現する方法を訊いているのか?
それじゃあ多分無理だ。
0706デフォルトの名無しさん
垢版 |
2019/08/09(金) 04:30:09.25ID:err5h/zJ
まあ尤もprintf sedなんていちいち呼び出すなんてバカなマネは普通しないが。
0709デフォルトの名無しさん
垢版 |
2019/08/09(金) 04:39:32.46ID:yPcnAt2h
shiftを上手く使えば
N番目以降の引数だけ別の処理に使うことってできるよね?
あとbashの引数って10超えるとおかしくなるってマジ?
0713デフォルトの名無しさん
垢版 |
2019/08/09(金) 05:33:56.10ID:err5h/zJ
>>707
じゃあこれでどう?
態々IFS弄ったり何度も置換したりする必要はない。
printf 'x%sz ' "$@" | sed -e 's/ $/\
/'
0714デフォルトの名無しさん
垢版 |
2019/08/09(金) 16:11:09.79ID:R8nkiB91
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

みたいな
0715デフォルトの名無しさん
垢版 |
2019/08/09(金) 17:22:23.99ID:tip6m9df
行と列をひっくり返す 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
0720デフォルトの名無しさん
垢版 |
2019/08/09(金) 18:42:56.05ID:xLAwVgGE
む。出遅れたか。気づいていたんだが書き込む時間がなかった。

>>716 と近いが、tsvなら入力をタブ文字にしたほうが良いだろう
でないとスペースまで区切りとして扱われる

paste hoge.tsv huga.tsv | awk -F"\t" -v OFS="\t" '{print $1,$2,$4,$5,$3}'
0721デフォルトの名無しさん
垢版 |
2019/08/09(金) 18:45:10.20ID:xLAwVgGE
>>718
それな。いかにも要求されてないことをやってるだろw
このスレ、例を出すと、その例を"だけ"に通用するコード書くやつ多いぞ
それを訂正するのに労力がかかるって言った意味わかるやろ?
0722デフォルトの名無しさん
垢版 |
2019/08/09(金) 18:48:55.70ID:xLAwVgGE
>>713
その答えもありだが、それはそれとして
引き数の a b c を xaz xbz xcz にするPOSIX準拠のテクニックって
あまり知られてないのか?
まさかこんなに出ないとは思わなかった。
0723デフォルトの名無しさん
垢版 |
2019/08/09(金) 19:01:27.20ID:xLAwVgGE
同時に二つのファイルを開くやり方も分かったことだし、
ついでにシェルスクリプトだけで実現するやり方を書いておこう

#!/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
■ このスレッドは過去ログ倉庫に格納されています

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