シェルスクリプト総合 その30
■ このスレッドは過去ログ倉庫に格納されています
シェルスクリプトに関する総合スレッドです。 全般 ・荒しは無視しましょう。 ・丁寧な姿勢を心掛けましょう。 ・ネチケット(死語)を意識しましょう。 前スレ: シェルスクリプト総合 その29 https://mevius.5ch.net/test/read.cgi/tech/1537540487/ 今調べてみたら .aaa.bbb[]と入力していたので全部一致してないとエラーになってたっぽいです .aaa.bbb[0]に変えている>>650 では一致してないところも空欄で出力されてましたので求めるものでした >>653 もしかして皮肉という概念をご存知ない…? >>655 それ配列ってことは要素数が1以上の場合もあるわけだよね 先頭だけでいいの? >>658 問題ないならいいけど [0] より []? 使ったほうが良いよ 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, って出力しかできぬ >>660 あんたが可変長引数を綺麗に勝利できないだけ printf '%s,' a b c a,b,c, printf 'x%sz,' a b c d e xaz,xbz,xcz,xdz,xez, >>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 ぶっちゃけ $@ を使ってどうやれば xa b c d ez, が出せるんだろうって悩むレベルw $ 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" としても可。 いけね、x と z で挟むの忘れてたわ $ l=;for v;do l="${l}${l:+,}x${v}z";done;echo "$l" >>660 や これを1まとめの変数にする方法ってあるか? bash test.sh a b c d って打つと↓を変数で使えるようにしたい(最後だけ,を外して) xaz,xbz,xcz,xdz ループさせて配列に入れて${test[@]}でxaz,xbz,xcz,xdz, って出力させることならできたけど最後の,が邪魔で仕方ない > これを1まとめの変数にする方法ってあるか? あるに決まってるだろ。 自分でやり方を模索しろや > 最後の,が邪魔で仕方ない ならつかないようにするか消せばいいだけだろ シェルスクリプト特有のテクニックがわからないならともかく 常識的なやり方すら見いだせないなら適性無いで マウント上等!教えてくれ! ${test[@]%,*}でいけると思ったが、これって配列じゃ無理なんか 悔しいねぇw >>668 こいつ昨日の>>626 か? 知識があるのは結構だが偏屈な理由でそれを教えようとしないのは目障りだからやめろ。 公共の場所だ,ちっとは考えて行動しろ。 もしも教えたくないのなら,最初から反応するな。 おいおい。IDみろよ。俺は重大な落とし穴があるで 教えんけどなー。みたいなことは言わない。 >>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 どうぞ。 シェルスクリプトにこだわっても意味内 単なる自己満足 >>674 evalいらねーだろ。その程度でいーばるーなよw あと、eval の -- は POSIX準拠じゃない。 dashではエラーになるな。 それと $@(と$var)にダブルクォートがついてないのもマイナス点だな >>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) 多分配列つめこんで paste で糊付けしてくれる paste はいわゆる join()のはず sed呼び出すぐらいならParameter expansionを使ったほうが楽で速いだろう お前らありがとう want="$(IFS=,; echo "${test[*]}"}" ってやったら求めるものが出せた >>677 bash前提のスクリプトなんですがそれは カッコの対応がおかしい。 サブシェルに入れる理由がないわけじゃないが、これで処理終了なら遅くなるだけ この程度でbash依存するのは無駄。長くなってるだけ >>683 じゃあbash 2.05aとそれ以前でエラーになると言っておこう ${l}${l:+,} は俺もよく使うが、ループで毎回比較処理をすることになるし、 最後に末尾処理をしたほうが、速いんじゃないかなーって 常々思ってしまう。lが二回出てくるから1行が長くなることが多いし 試してみたけどやっぱりだ。最後に末尾処理するほうが速い。 dashやkshだと2倍ぐらい差が出る。 bashやzshはこういう処理が何故か遅くて差もあまり出ないけど Ruby では、Array#join で自動的に、最後の区切り文字を削除してくれる ary = [ "a", "b" ] p ary.join( "," ) #=> "a,b" そりゃそうだ joinは配列から文字列に変換するときに 間の糊付けをしてくれるのだから 単純な join でセパレータが一文字なら定番の $ (IFS=,; echo "$*") で良いのだろうけど >>688 1行でできるから:+を使いたくなるけどね。 でも変数名が長いと見づらくなっちゃう。 余計なものをくっつけて、最後に削るのは一見無駄なことをしてるように思えるけど そっちの方が速いってはっきりしたので、これからは気兼ねなく、 :+を使わない方法を使えるようになったよ >>691 コマンド置換だと遅くなるよ。 IFS=,; echo "$*" でいいでしょ? IFSを戻したいなら戻せばいいだけだし。 それに変数に入れる場合、var="$*" だと最後の改行もちゃんと保存されるけど コマンド置換を使うと消えてしまう。 >>691 で > 単純な join でセパレータが一文字なら という話が出たので、問題。 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが それでもIFS=,を使うならばどうすればよいだろうか? 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、 さてどうすればよいだろうか? そんな面倒なことをシェルスクリプトでやるのはやめる 客が7&いじゃなければ大丈夫だろ >>667 $ var=$(printf "x${1}z";shift;(($#)) && printf ',%sz' "${@/#/x}") >>694 $ (set -- "${@/#/x}";set -- "${@/%/z}";IFS=,;echo "$*") >>697 とっても無理矢理感があるなw まず引き数がないときに、xzと表示されるバグが有る。 あと後半意味がわからんw 単純に && printf ',x%sz' "$@" でいいんでないの? (($#))もいらんし >>698 なるほど。bash依存だとそれができるのか。それは盲点だった。 書いてなかったけど、POSIX準拠の場合はどうなるだろうか? >>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}"; }) おっと、 var=$((($#))&&{ printf "x${1}z";shift;(($#))&&printf ',x%sz' "$@"; }) だね ああprintfは引き数がない場合でも表示されるのか >>673 仮に別人だとしても同じようなことしてるぞ。 自分で模索しろとか言って解法を提示していないにもかかわらず ある程度要求を満たす解法が上がった瞬間それにケチ付けはじめてるじゃん。 もしもほんとうに「自分で模索しろ」って思ってんなら黙っときゃいい話。 わざわざ人が答えを述べてからそれに乗っかるなんてマネする必要ない。 >>700 このコマンドラインをPOSIXに準じたものにするには (愚直に言えば)単に${VAR/aaa/bbb}をprintf '%s' "$VAR" | sed -e 's/aaa/bbb/' に変えればいいだけでは? それかPOSIXの範疇で変数の置換展開を実現する方法を訊いているのか? それじゃあ多分無理だ。 まあ尤もprintf sedなんていちいち呼び出すなんてバカなマネは普通しないが。 >>705 違うでー、引き数の a b c を xaz xbz xcz にする方法を 聞いてるんだぜー このテクニックはいろいろと応用が効くのだ!キリッ! shiftを上手く使えば N番目以降の引数だけ別の処理に使うことってできるよね? あとbashの引数って10超えるとおかしくなるってマジ? >>709 嘘 ${10} を使えばいい。 (相当古いシェルは非対応だったりするらしいが) 引数をうまく扱うにはshift、 引数を高度に扱うにはevalを使う >>707 じゃあこれでどう? 態々IFS弄ったり何度も置換したりする必要はない。 printf 'x%sz ' "$@" | sed -e 's/ $/\ /' 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 みたいな 行と列をひっくり返す 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 >>714 paste hoge.tsv huga.tsv | awk 'BEGIN{OFS="\t"}{print $1,$2,$4,$5,$3}' a b c d e 1 2 3 4 5 >>715 こっちのやりかたのほうが汎用的だし個人的には好きかな。 (´-`).。oO(列の挿入なのに何故ソートするんだろう) む。出遅れたか。気づいていたんだが書き込む時間がなかった。 >>716 と近いが、tsvなら入力をタブ文字にしたほうが良いだろう でないとスペースまで区切りとして扱われる paste hoge.tsv huga.tsv | awk -F"\t" -v OFS="\t" '{print $1,$2,$4,$5,$3}' >>718 それな。いかにも要求されてないことをやってるだろw このスレ、例を出すと、その例を"だけ"に通用するコード書くやつ多いぞ それを訂正するのに労力がかかるって言った意味わかるやろ? >>713 その答えもありだが、それはそれとして 引き数の a b c を xaz xbz xcz にするPOSIX準拠のテクニックって あまり知られてないのか? まさかこんなに出ないとは思わなかった。 同時に二つのファイルを開くやり方も分かったことだし、 ついでにシェルスクリプトだけで実現するやり方を書いておこう #!/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 >>720 おおおおおおありがてぇ! 区切りもタブ指定しないとyyyy-mm-dd hh-mm-ssとかがずれるよね GNU datamashってのがあんだね。 $ paste hoge.tsv huga.tsv | datamash transpose | sort | datamash transpose とか。挿入じゃなくてソートだけど。 ソートしたのは >>714 で hoge.tsv と huga.tsv の一行目の項目が辞書順に 並ぶ様に挿入する、って思ったんだよね >>720 FSのデフォルトはスペースとタブだから指定する必要ないよ なんかこのスレに書き込む質問者ってお客は神様だみたいな発想してる人多い印象がある。 多少の問題は自力で解決しろよって思うわ。 「その例"だけ"に〜」とか喚いてるけど,その「例」とやらがマズい例なのでは?とは1ミリも考えてなさそう。 いつも自分が正しい。問題の責任は他人にある。 まあスレの全員がそうじゃないけどね。極一部。 >>728 アホか、スペースとタブだからタブだけにするんやろw >>729 例っつーのはな、本題があって、それを補足するためのものなんだよ。 本題が本当にやりたいこと、 お前>>714 本題の文章「awkとか使ってtsvを別のtsvに挿入させる方法ってある?」 読んで、ソートしたいって思うか? お前は「いつも自分の解答が正しい。問題の責任は質問した他人にある。」 と考えてるんやろ? (´-`).。oO(勘違いしたって言ってるんだからもうええやん) >>694 の問題は本日24:00で締め切るでー シェルスクリプトに詳しいと思ってる人、 挑戦してみてやー >>733 スレ更新してから書き込むまでに、34秒以上かかっただけだよw しゅ‐き【主気】 ?名? そのものがいつも持っている運気。⇔客気(かっき)。〔夢渓筆談‐象数・一〕 はい、24:00締め切りでーす。 > 引き数 a b c を xaz xbz xcz にすればいいわけだが、 > さてどうすればよいだろうか? 解答 for i in "$@"; do set -- "$@" "x${i}z" shift done 別解 for i in "$@"; do set -- "$@" "x${i}z" done shift $(($# / 2)) なんか対抗するつもりはないけど俺の回答のほうが何やってるか分かりやすい気がする…。 まあトリッキーなシェルスクリプトを書くのは個人の自由だけど >>742 こんなのトリッキーのうちに入らんでしょ。 シャルスクリプト特有の書き方ってだけ POSIXの範囲ではシェルスクリプトで使える配列は パラメータ引数しか無い。その貴重な配列を使いこなせば bash依存もせずにすむよ bashでいいじゃん bash動かないようなクソ環境なんかないだろ今時 POSIX原理主義者の彼にはそんな煽りは通用しない! そのとおり。Debianがdashを使ってるのだ。どうしようもない。 >>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>. と書かれてるんだけど。 bash依存っていうのは ${test[@]} とか printf ',%sz' "${@/#/x}" のことな >>713 に関して言えば、 引き数の a b c を xaz xbz xcz にする方法を聞いてるのに 質問の答になってないねとしか言えないから >>750 うん? $ cat ./test.sh #!/bin/sh printf 'x%sz ' "$@" | sed -e 's/ $/\ /' $ ./test.sh a b c xaz xbz xcz となって要求を満してそうなんだけども,違うのかな? >>694 再掲 > 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが > それでもIFS=,を使うならばどうすればよいだろうか? > > 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、 > さてどうすればよいだろうか? >>738 または>>739 でパラメータ引数$@に入ってないと IFS=,を使って xaz,xbz,xcz にすることができないだろ 問題をちゃんと読んでいれば、わかるはずのことだが $@ の中身が printable character だけなら GNU awk の SUBSEP 変数と同じ 様に IFS に '\034'(File Separator) を指定して [ $# -eq 0 ] && exit 0 IFS=$(printf '\034');set -- $(printf "x%sz${IFS}" "$@") IFS=,;echo "$*" とか ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる