X



シェルスクリプト総合 その30
■ このスレッドは過去ログ倉庫に格納されています
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
0726デフォルトの名無しさん
垢版 |
2019/08/09(金) 19:10:00.87ID:X5pM/Zqg
GNU datamashってのがあんだね。
$ paste hoge.tsv huga.tsv | datamash transpose | sort | datamash transpose
とか。挿入じゃなくてソートだけど。
0727デフォルトの名無しさん
垢版 |
2019/08/09(金) 19:14:10.02ID:tip6m9df
ソートしたのは >>714 で hoge.tsv と huga.tsv の一行目の項目が辞書順に
並ぶ様に挿入する、って思ったんだよね
0729デフォルトの名無しさん
垢版 |
2019/08/09(金) 19:21:36.74ID:err5h/zJ
なんかこのスレに書き込む質問者ってお客は神様だみたいな発想してる人多い印象がある。
多少の問題は自力で解決しろよって思うわ。
「その例"だけ"に〜」とか喚いてるけど,その「例」とやらがマズい例なのでは?とは1ミリも考えてなさそう。
いつも自分が正しい。問題の責任は他人にある。

まあスレの全員がそうじゃないけどね。極一部。
0732デフォルトの名無しさん
垢版 |
2019/08/09(金) 19:25:33.15ID:xLAwVgGE
>>729
例っつーのはな、本題があって、それを補足するためのものなんだよ。
本題が本当にやりたいこと、

お前>>714本題の文章「awkとか使ってtsvを別のtsvに挿入させる方法ってある?」
読んで、ソートしたいって思うか?

お前は「いつも自分の解答が正しい。問題の責任は質問した他人にある。」
と考えてるんやろ?
0734デフォルトの名無しさん
垢版 |
2019/08/09(金) 19:28:06.46ID:xLAwVgGE
>>694の問題は本日24:00で締め切るでー
シェルスクリプトに詳しいと思ってる人、
挑戦してみてやー
0737デフォルトの名無しさん
垢版 |
2019/08/09(金) 19:34:19.38ID:xLAwVgGE
しゅ‐き【主気】
?名? そのものがいつも持っている運気。⇔客気(かっき)。〔夢渓筆談‐象数・一〕
0738デフォルトの名無しさん
垢版 |
2019/08/10(土) 00:01:07.05ID:L+B8OP2P
はい、24:00締め切りでーす。

> 引き数 a b c を xaz xbz xcz にすればいいわけだが、
> さてどうすればよいだろうか?

解答

for i in "$@"; do
 set -- "$@" "x${i}z"
 shift
done
0739デフォルトの名無しさん
垢版 |
2019/08/10(土) 00:04:08.85ID:L+B8OP2P
別解

for i in "$@"; do
 set -- "$@" "x${i}z"
done
shift $(($# / 2))
0741デフォルトの名無しさん
垢版 |
2019/08/10(土) 00:14:33.81ID:L+B8OP2P
知らんがな
0742デフォルトの名無しさん
垢版 |
2019/08/10(土) 01:26:32.09ID:lTTXvTcQ
なんか対抗するつもりはないけど俺の回答のほうが何やってるか分かりやすい気がする…。
まあトリッキーなシェルスクリプトを書くのは個人の自由だけど
0743デフォルトの名無しさん
垢版 |
2019/08/10(土) 01:56:14.18ID:L+B8OP2P
>>742
こんなのトリッキーのうちに入らんでしょ。
シャルスクリプト特有の書き方ってだけ

POSIXの範囲ではシェルスクリプトで使える配列は
パラメータ引数しか無い。その貴重な配列を使いこなせば
bash依存もせずにすむよ
0748デフォルトの名無しさん
垢版 |
2019/08/10(土) 02:58:22.15ID:lTTXvTcQ
>>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>.
と書かれてるんだけど。
0750デフォルトの名無しさん
垢版 |
2019/08/10(土) 03:03:44.77ID:L+B8OP2P
>>713に関して言えば、
引き数の a b c を xaz xbz xcz にする方法を聞いてるのに
質問の答になってないねとしか言えないから
0751デフォルトの名無しさん
垢版 |
2019/08/10(土) 03:10:55.16ID:lTTXvTcQ
>>750
うん?
$ cat ./test.sh
#!/bin/sh

printf 'x%sz ' "$@" | sed -e 's/ $/\
/'
$ ./test.sh a b c
xaz xbz xcz
となって要求を満してそうなんだけども,違うのかな?
0752デフォルトの名無しさん
垢版 |
2019/08/10(土) 03:11:46.31ID:L+B8OP2P
>>694 再掲

> 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが
> それでもIFS=,を使うならばどうすればよいだろうか?
>
> 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、
> さてどうすればよいだろうか?

>>738または>>739でパラメータ引数$@に入ってないと
IFS=,を使って xaz,xbz,xcz にすることができないだろ
問題をちゃんと読んでいれば、わかるはずのことだが
0754デフォルトの名無しさん
垢版 |
2019/08/10(土) 03:35:54.66ID:6d2gRK68
$@ の中身が printable character だけなら GNU awk の SUBSEP 変数と同じ
様に IFS に '\034'(File Separator) を指定して

[ $# -eq 0 ] && exit 0
IFS=$(printf '\034');set -- $(printf "x%sz${IFS}" "$@")
IFS=,;echo "$*"

とか
0756デフォルトの名無しさん
垢版 |
2019/08/10(土) 03:43:06.24ID:L+B8OP2P
訂正
それだと "a b" のように引数にスペースが入ってるときにうまく動かない
0758デフォルトの名無しさん
垢版 |
2019/08/10(土) 03:50:33.54ID:6d2gRK68
set -- a "b c" d
IFS=$(printf '\034');set -- $(printf "x%sz${IFS}" "$@")
IFS=,;echo "$*"

とすると xaz,xb cz,xdz となるのだが、そういう事じゃなくて?
0759デフォルトの名無しさん
垢版 |
2019/08/10(土) 03:54:52.71ID:L+B8OP2P
>>758
うん。だから見落としてたw

そうだな。あとはサブシェルを使うから遅いのと、
それよりも、zshだと
$ ./test.sh a b c
xaz,xbz,xcz,
最後に,がつく
0762デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:01:38.59ID:lTTXvTcQ
>>760
Bashとか持ち出すとbash 2.xとか今現在どこでも使われていないバージョンのことも考えないといけなくなるぞw
Solarisでさえbash 4なのにw
0764デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:04:55.05ID:6d2gRK68
>>759
zsh だと set -- $(printf "x%sz${IFS}" "$@") 後の $# の値が 4 になるのね
POSIX 的には $# == 3 になるのが正しい動作なのかね?
0765デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:06:36.42ID:lTTXvTcQ
>>752
訊きたいんだけど,
引数を完全に置き換えてしまうことについてはどう思ってる?

再掲するけど
> (問題文に書いてないので推測するしかないが)引数自体はそのまま残したい場合もあるだろうから
> 引数を置き換えてしまう方法だと不本意な結果を招くかもしれないとも思った。

引数自体を弄くる方法だとこういうことになるのでは……?
0767デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:09:03.91ID:L+B8OP2P
>>761
> ぽじっくすに拘ったりぜっしゅに拘ったり急がしやっちゃなw

何いってんの? POSIX互換シェルにこだわってるだけだよ。
POSIXもdashもzshもbashもワケてない
POSIX互換シェルという一つのこだわりw
0768デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:11:01.54ID:L+B8OP2P
>>763
> set -uしてると引数が存在しない場合に古いシェルで動かない

苦笑(知ってるw)

間違ってないが、具体的にどのシェルで動かないか言えるかい?
0769デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:14:17.41ID:L+B8OP2P
>>764
> POSIX 的には $# == 3 になるのが正しい動作なのかね?
めんどくさくて調べてないな。

でもzshだけではなく、今は使われてないだろう古いシェルや
とあるシェルの古いバージョンでは4で、後のバージョンでは3になってたりするから
おそらく $# == 3 が正しいのだろう。

だが、現実として動かないシェルがある
POSIX互換シェルに拘ってるといったが、正確にはPOSIX互換シェルと名乗っている
現実に存在するシェルに拘っているというべきか
0771デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:15:21.60ID:lTTXvTcQ
ZshってPOSIX互換を謳ってたっけ?
少なくとも公式ページ[zsh.org]にはそんな記述は見当らんが…。
もしかしてemulate -R shをPOSIX準拠モードとかだと思ってる…?
0772デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:19:09.04ID:lTTXvTcQ
>>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
0773デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:20:00.43ID:L+B8OP2P
>>762
Solarisは10まで(POSIX互換ではない)Bourne Shellが
デフォルトシェルだってのがいただけない
Extended Supportが2021年までらしい。
まあ俺はPOSIXじゃないからという理由で切り捨てることにしてるが
0774デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:20:29.77ID:lTTXvTcQ
>>694
> 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが →分かる
> それでもIFS=,を使うならばどうすればよいだろうか?→そうだな,どうすればいいんだろう。

> 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、→え?空白区切り?今IFS=,の話だよな??
> さてどうすればよいだろうか? →????
0775デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:23:34.50ID:L+B8OP2P
>>772

>>694再掲 読める?

> 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが
> それでもIFS=,を使うならばどうすればよいだろうか?
0776デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:26:01.61ID:L+B8OP2P
>>774
お前プログラマに向いてないよw
推論能力が圧倒的に不足してる

引数が、xaz xbz xcz の状態なら、IFS使って xaz,xbz,xcz にできるだろw

って言っても理解できないんだろうなw
0778デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:29:01.72ID:L+B8OP2P
>>771
zshのマニュアルにはPOSIXという文字が50個以上存在する
これでPOSIXを意識してないとか考えられんわw
0780デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:35:32.28ID:6d2gRK68
>>778
Zsh is able to emulate POSIX shells, but its default mode is not POSIX compatible

なんて書いてあるから何か変数を設定しないとダメみたいだな
色々弄ってるけど $# が 3 にならんのぅ…ソースコード読むしかないかなw
0782デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:41:34.35ID:L+B8OP2P
>>768の質問には答えてくれないのかな?
set -uしてると引数が存在しない場合に動かない古いシェルはなにか?
0783デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:42:42.71ID:lTTXvTcQ
>>776
うんだってプログラマじゃねーもんw

寧ろその程度の能力でイキれるお前がプログラマっぽくねぇなw

こっちの類推能力も足りんかもしれんが
そっちの説明能力もかなり欠如してんぞw
0785デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:44:17.65ID:L+B8OP2P
別にイキってないが、イキってるように見えるのは
俺じゃなくて、お前の問題でしょう? 普通のことなのにお前にはそう見えてしまう。
0786デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:45:41.26ID:L+B8OP2P
>>784
何に答えればいいの?

引数を完全に起きかえたいなら置き換えればいいし
置き換えたくないならば、置き換えなければいいだけじゃん
0787デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:49:56.25ID:L+B8OP2P
なんで>>765みたいな質問が来るのかを推測したが、
提示したコードはそれで「完成したコード」で
そのコードを修正した「応用」は存在しないとか思ってないか?
違うことをしたいならそれに応じて変えればよかろう?
0789デフォルトの名無しさん
垢版 |
2019/08/10(土) 04:57:52.03ID:lTTXvTcQ
>>785
うーむ。自省という言葉を教えてあげたいw
まあある程度シェルスクリプトの能力はありそうだが
それ以外が致命的とお見受けするわ……。

ていうかシェルスクリプトの能力ってそんな高める必要ある?
>>713程度が書ければそれで十分。
より高度な,それこそJSONやXMLみたいな階層構造のある
「1行1データ」とは限らない形式のファイルを読み込みたけりゃ,
CなりPerlなりを使えばよろしい。
もしくはjqやらxmllintやらで適切に処理して
シェルスクリプトに掛ければよろしい。
0790デフォルトの名無しさん
垢版 |
2019/08/10(土) 05:00:56.32ID:L+B8OP2P
>>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
0791デフォルトの名無しさん
垢版 |
2019/08/10(土) 05:03:11.51ID:L+B8OP2P
>>789
> ていうかシェルスクリプトの能力ってそんな高める必要ある?

俺がやりたいことを実現するのに必須だったから
自然と高くなっただけ
■ このスレッドは過去ログ倉庫に格納されています

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